1 /**
2  * @file
3  * @brief Functions used to save and load levels/games.
4 **/
5 
6 // old compiler compatibility for CAO/CBRO stdint.h. cstdint doesn't work
7 // on these gcc versions to provide UINT8_MAX.
8 #ifndef  __STDC_LIMIT_MACROS
9 #define  __STDC_LIMIT_MACROS 1
10 #endif
11 #include <stdint.h>
12 
13 #include "AppHdr.h"
14 
15 #include "files.h"
16 
17 #include "json.h"
18 #include "json-wrapper.h"
19 
20 #include <algorithm>
21 #include <cctype>
22 #include <cerrno>
23 #include <cstdio>
24 #include <cstdlib>
25 #include <cstring>
26 #include <functional>
27 #include <string>
28 #include <fcntl.h>
29 #include <sys/stat.h>
30 #ifdef HAVE_UTIMES
31 #include <sys/time.h>
32 #endif
33 #include <sys/types.h>
34 #ifdef UNIX
35 #include <unistd.h>
36 #endif
37 
38 #include "abyss.h"
39 #include "act-iter.h"
40 #include "areas.h"
41 #include "branch.h"
42 #include "chardump.h"
43 #include "cloud.h"
44 #include "coordit.h"
45 #include "dactions.h"
46 #include "dbg-util.h"
47 #include "dgn-overview.h"
48 #include "directn.h"
49 #include "dungeon.h"
50 #include "end.h"
51 #include "tile-env.h"
52 #include "errors.h"
53 #include "player-save-info.h"
54 #include "fineff.h"
55 #include "ghost.h"
56 #include "god-abil.h"
57 #include "god-companions.h"
58 #include "god-passive.h"
59 #include "hints.h"
60 #include "initfile.h"
61 #include "item-name.h"
62 #include "items.h"
63 #include "jobs.h"
64 #include "kills.h"
65 #include "level-state-type.h"
66 #include "libutil.h"
67 #include "macro.h"
68 #include "mapmark.h"
69 #include "message.h"
70 #include "mon-behv.h"
71 #include "mon-death.h"
72 #include "mon-place.h"
73 #include "notes.h"
74 #include "place.h"
75 #include "prompt.h"
76 #include "skills.h"
77 #include "species.h"
78 #include "spl-summoning.h"
79 #include "stairs.h"
80 #include "state.h"
81 #include "stringutil.h"
82 #include "syscalls.h"
83 #include "tag-version.h"
84 #include "teleport.h"
85 #include "terrain.h"
86 #ifdef USE_TILE
87  // TODO -- dolls
88  #include "rltiles/tiledef-player.h"
89  #include "tilepick-p.h"
90 #endif
91 #include "tileview.h"
92 #include "tiles-build-specific.h"
93 #include "timed-effects.h"
94 #include "ui.h"
95 #include "unwind.h"
96 #include "version.h"
97 #include "view.h"
98 #include "xom.h"
99 
100 #ifdef __ANDROID__
101 #include <android/log.h>
102 #endif
103 
104 #ifndef F_OK // MSVC for example
105 #define F_OK 0
106 #endif
107 
108 #define BONES_DIAGNOSTICS (defined(WIZARD) || defined(DEBUG_BONES) || defined(DEBUG_DIAGNOSTICS))
109 
110 #ifdef BONES_DIAGNOSTICS
111 /// show diagnostics following a wizard command, even if not a debug build
_ghost_dprf(const char * format,...)112 static void _ghost_dprf(const char *format, ...)
113 {
114     va_list argp;
115     va_start(argp, format);
116 
117 #ifndef DEBUG_DIAGNOSTICS
118     const bool wiz_cmd = (crawl_state.prev_cmd == CMD_WIZARD);
119     if (wiz_cmd)
120 #endif
121         do_message_print(MSGCH_DIAGNOSTICS, 0, false, false, format, argp);
122 
123     va_end(argp);
124 }
125 #else
126 # define _ghost_dprf(...) ((void)0)
127 #endif
128 
129 static bool _ghost_version_compatible(const save_version &version);
130 
131 static bool _restore_tagged_chunk(package *save, const string &name,
132                                   tag_type tag, const char* complaint);
133 static bool _read_char_chunk(package *save);
134 
135 static bool _convert_obsolete_species();
136 
137 const short GHOST_SIGNATURE = short(0xDC55);
138 
139 const int GHOST_LIMIT = 27; // max number of ghost files per level
140 
_redraw_all()141 static void _redraw_all()
142 {
143     you.redraw_hit_points    = true;
144     you.redraw_magic_points  = true;
145     you.redraw_stats.init(true);
146     you.redraw_armour_class  = true;
147     you.redraw_evasion       = true;
148     you.redraw_experience    = true;
149     you.redraw_status_lights = true;
150 }
151 
is_save_file_name(const string & name)152 static bool is_save_file_name(const string &name)
153 {
154     int off = name.length() - strlen(SAVE_SUFFIX);
155     if (off <= 0)
156         return false;
157     return !strcasecmp(name.c_str() + off, SAVE_SUFFIX);
158 }
159 
160 // Returns the save_info from the save.
_read_character_info(package * save)161 static player_save_info _read_character_info(package *save)
162 {
163     player_save_info fromfile;
164 
165     // Backup before we clobber "you".
166     const player backup(you);
167     unwind_var<game_type> gtype(crawl_state.type);
168 
169     try // need a redundant try block just so we can restore the backup
170     {   // (or risk an = operator on you getting misused)
171         fromfile.save_loadable = _read_char_chunk(save);
172         fromfile = you;
173     }
174     catch (ext_fail_exception &E) {}
175 
176     you = backup;
177 
178     return fromfile;
179 }
180 
get_dir_files_sorted(const string & dirname)181 vector<string> get_dir_files_sorted(const string &dirname)
182 {
183     auto result = get_dir_files(dirname);
184     sort(result.begin(), result.end());
185     return result;
186 }
187 
188 // Returns a vector of files (including directories if requested) in
189 // the given directory, recursively. All filenames returned are
190 // relative to the start directory. If an extension is supplied, all
191 // filenames (and directory names if include_directories is set)
192 // returned must be suffixed with the extension (the extension is not
193 // modified in any way, so if you want, say, ".des", you must include
194 // the "." as well).
195 //
196 // If recursion_depth is -1, the recursion is infinite, as far as the
197 // directory structure and filesystem allows. If recursion_depth is 0,
198 // only files in the start directory are returned.
get_dir_files_recursive(const string & dirname,const string & ext,int recursion_depth,bool include_directories)199 vector<string> get_dir_files_recursive(const string &dirname, const string &ext,
200                                        int recursion_depth,
201                                        bool include_directories)
202 {
203     vector<string> files;
204 
205     const int next_recur_depth =
206         recursion_depth == -1? -1 : recursion_depth - 1;
207     const bool recur = recursion_depth == -1 || recursion_depth > 0;
208 
209     for (const string &filename : get_dir_files_sorted(dirname))
210     {
211         if (dir_exists(catpath(dirname, filename)))
212         {
213             if (include_directories
214                 && (ext.empty() || ends_with(filename, ext)))
215             {
216                 files.push_back(filename);
217             }
218 
219             if (recur)
220             {
221                 // Each filename in a subdirectory has to be prefixed
222                 // with the subdirectory name.
223                 for (const string &subdirfile
224                         : get_dir_files_recursive(catpath(dirname, filename),
225                                                   ext, next_recur_depth))
226                 {
227                     files.push_back(catpath(filename, subdirfile));
228                 }
229             }
230         }
231         else
232         {
233             if (ext.empty() || ends_with(filename, ext))
234                 files.push_back(filename);
235         }
236     }
237     return files;
238 }
239 
get_dir_files_ext(const string & dir,const string & ext)240 vector<string> get_dir_files_ext(const string &dir, const string &ext)
241 {
242     return get_dir_files_recursive(dir, ext, 0);
243 }
244 
get_parent_directory(const string & filename)245 string get_parent_directory(const string &filename)
246 {
247     string::size_type pos = filename.rfind(FILE_SEPARATOR);
248     if (pos != string::npos)
249         return filename.substr(0, pos + 1);
250 #ifdef ALT_FILE_SEPARATOR
251     pos = filename.rfind(ALT_FILE_SEPARATOR);
252     if (pos != string::npos)
253         return filename.substr(0, pos + 1);
254 #endif
255     return "";
256 }
257 
get_base_filename(const string & filename)258 string get_base_filename(const string &filename)
259 {
260     string::size_type pos = filename.rfind(FILE_SEPARATOR);
261     if (pos != string::npos)
262         return filename.substr(pos + 1);
263 #ifdef ALT_FILE_SEPARATOR
264     pos = filename.rfind(ALT_FILE_SEPARATOR);
265     if (pos != string::npos)
266         return filename.substr(pos + 1);
267 #endif
268     return filename;
269 }
270 
get_cache_name(const string & filename)271 string get_cache_name(const string &filename)
272 {
273     string::size_type pos = filename.rfind(FILE_SEPARATOR);
274     while (pos != string::npos && filename.find("/des", pos) != pos)
275         pos = filename.rfind(FILE_SEPARATOR, pos - 1);
276     if (pos != string::npos)
277         return replace_all_of(filename.substr(pos + 5), " /\\:", "_");
278 #ifdef ALT_FILE_SEPARATOR
279     pos = filename.rfind(ALT_FILE_SEPARATOR);
280     while (pos != string::npos && filename.find("/des", pos) != pos)
281         pos = filename.rfind(ALT_FILE_SEPARATOR, pos - 1);
282     if (pos != string::npos)
283         return replace_all_of(filename.substr(pos + 5), " /\\:", "_");
284 #endif
285     return filename;
286 }
287 
is_absolute_path(const string & path)288 bool is_absolute_path(const string &path)
289 {
290     return !path.empty()
291            && (path[0] == FILE_SEPARATOR
292 #ifdef TARGET_OS_WINDOWS
293                || path.find(':') != string::npos
294 #endif
295              );
296 }
297 
298 // Concatenates two paths, separating them with FILE_SEPARATOR if necessary.
299 // Assumes that the second path is not absolute.
300 //
301 // If the first path is empty, returns the second unchanged. The second path
302 // may be absolute in this case.
catpath(const string & first,const string & second)303 string catpath(const string &first, const string &second)
304 {
305     if (first.empty())
306         return second;
307 
308     string directory = first;
309     if (directory[directory.length() - 1] != FILE_SEPARATOR
310         && (second.empty() || second[0] != FILE_SEPARATOR))
311     {
312         directory += FILE_SEPARATOR;
313     }
314     directory += second;
315 
316     return directory;
317 }
318 
319 // Given a relative path and a reference file name, returns the relative path
320 // suffixed to the directory containing the reference file name. Assumes that
321 // the second path is not absolute.
get_path_relative_to(const string & referencefile,const string & relativepath)322 string get_path_relative_to(const string &referencefile,
323                             const string &relativepath)
324 {
325     return catpath(get_parent_directory(referencefile),
326                    relativepath);
327 }
328 
change_file_extension(const string & filename,const string & ext)329 string change_file_extension(const string &filename, const string &ext)
330 {
331     const string::size_type pos = filename.rfind('.');
332     return (pos == string::npos? filename : filename.substr(0, pos)) + ext;
333 }
334 
file_modtime(const string & file)335 time_t file_modtime(const string &file)
336 {
337     struct stat filestat;
338     if (stat(file.c_str(), &filestat))
339         return 0;
340 
341     return filestat.st_mtime;
342 }
343 
file_modtime(FILE * f)344 time_t file_modtime(FILE *f)
345 {
346     struct stat filestat;
347     if (fstat(fileno(f), &filestat))
348         return 0;
349 
350     return filestat.st_mtime;
351 }
352 
_create_directory(const char * dir)353 static bool _create_directory(const char *dir)
354 {
355     if (!mkdir_u(dir, 0755))
356         return true;
357     if (errno == EEXIST) // might be not a directory
358         return dir_exists(dir);
359     return false;
360 }
361 
_create_dirs(const string & dir)362 static bool _create_dirs(const string &dir)
363 {
364     string sep = " ";
365     sep[0] = FILE_SEPARATOR;
366     vector<string> segments = split_string(sep, dir, false, false);
367 
368     string path;
369     for (int i = 0, size = segments.size(); i < size; ++i)
370     {
371         path += segments[i];
372 
373         // Handle absolute paths correctly.
374         if (i == 0 && dir.size() && dir[0] == FILE_SEPARATOR)
375             path = FILE_SEPARATOR + path;
376 
377         if (!_create_directory(path.c_str()))
378             return false;
379 
380         path += FILE_SEPARATOR;
381     }
382     return true;
383 }
384 
385 // Checks whether the given path is safe to read from. A path is safe if:
386 // 1. If Unix: It contains no shell metacharacters.
387 // 2. If DATA_DIR_PATH is set: the path is not an absolute path.
388 // 3. If DATA_DIR_PATH is set: the path contains no ".." sequence.
assert_read_safe_path(const string & path)389 void assert_read_safe_path(const string &path)
390 {
391     // Check for rank tomfoolery first:
392     if (path.empty())
393         throw unsafe_path("Empty file name.");
394 
395 #ifdef UNIX
396     if (!shell_safe(path.c_str()))
397         throw unsafe_path_f("\"%s\" contains bad characters.", path.c_str());
398 #endif
399 
400 #ifdef DATA_DIR_PATH
401     if (is_absolute_path(path))
402         throw unsafe_path_f("\"%s\" is an absolute path.", path.c_str());
403 
404     if (path.find("..") != string::npos)
405         throw unsafe_path_f("\"%s\" contains \"..\" sequences.", path.c_str());
406 #endif
407 
408     // Path is okay.
409 }
410 
canonicalise_file_separator(const string & path)411 string canonicalise_file_separator(const string &path)
412 {
413     const string sep(1, FILE_SEPARATOR);
414     return replace_all_of(replace_all_of(path, "/", sep),
415                           "\\", sep);
416 }
417 
_get_base_dirs()418 static vector<string> _get_base_dirs()
419 {
420     const string rawbases[] =
421     {
422 #ifdef DATA_DIR_PATH
423         DATA_DIR_PATH,
424 #else
425         !SysEnv.crawl_dir.empty()? SysEnv.crawl_dir : "",
426         !SysEnv.crawl_base.empty()? SysEnv.crawl_base : "",
427 #endif
428 #ifdef TARGET_OS_MACOSX
429         SysEnv.crawl_base + "../Resources/",
430 #endif
431 #ifdef __ANDROID__
432         ANDROID_ASSETS,
433         "/sdcard/Android/data/org.develz.crawl/files/",
434 #endif
435     };
436 
437     const string prefixes[] =
438     {
439         string("dat") + FILE_SEPARATOR,
440 #ifdef USE_TILE_LOCAL
441         string("dat/tiles") + FILE_SEPARATOR,
442 #endif
443         string("docs") + FILE_SEPARATOR,
444         string("settings") + FILE_SEPARATOR,
445 #ifndef DATA_DIR_PATH
446         string("..") + FILE_SEPARATOR + "docs" + FILE_SEPARATOR,
447         string("..") + FILE_SEPARATOR + "dat" + FILE_SEPARATOR,
448 #ifdef USE_TILE_LOCAL
449         string("..") + FILE_SEPARATOR + "dat/tiles" + FILE_SEPARATOR,
450 #endif
451         string("..") + FILE_SEPARATOR + "settings" + FILE_SEPARATOR,
452         string("..") + FILE_SEPARATOR,
453 #endif
454         "",
455     };
456 
457     vector<string> bases;
458     for (string base : rawbases)
459     {
460         if (base.empty())
461             continue;
462 
463         base = canonicalise_file_separator(base);
464 
465         if (base[base.length() - 1] != FILE_SEPARATOR)
466             base += FILE_SEPARATOR;
467 
468         for (unsigned p = 0; p < ARRAYSZ(prefixes); ++p)
469             bases.push_back(base + prefixes[p]);
470     }
471 
472     return bases;
473 }
474 
validate_basedirs()475 void validate_basedirs()
476 {
477     // TODO: could use this to pick a single data directory?
478     vector<string> bases(_get_base_dirs());
479     bool found = false;
480 
481     // there are a few others, but this should be enough to minimally run something
482     const vector<string> data_subfolders =
483     {
484         "clua",
485         "database",
486         "defaults",
487         "des",
488         "descript",
489         "dlua"
490 #ifdef USE_TILE_LOCAL
491         , "tiles"
492 #endif
493     };
494 
495     for (const string &d : bases)
496     {
497         if (dir_exists(d))
498         {
499             bool everything = true;
500             bool something = false;
501             for (auto subdir : data_subfolders)
502             {
503                 if (dir_exists(d + subdir))
504                     something = true;
505                 else
506                     everything = false;
507             }
508             if (everything)
509             {
510                 mprf(MSGCH_PLAIN, "Data directory '%s' found.", d.c_str());
511                 found = true;
512             }
513             else if (something)
514             {
515                 // give an error for this case because this incomplete data
516                 // directory will be checked before others, possibly leading
517                 // to a weird mix of data files.
518                 if (!found)
519                 {
520                     mprf(MSGCH_ERROR,
521                         "Incomplete or corrupted data directory '%s'",
522                                 d.c_str());
523                 }
524             }
525         }
526     }
527 
528     // can't proceed if nothing complete was found.
529     if (!found)
530     {
531         string err = "Missing DCSS data directory; tried: \n";
532         err += comma_separated_line(bases.begin(), bases.end());
533 
534         end(1, false, "%s", err.c_str());
535     }
536 }
537 
datafile_path(string basename,bool croak_on_fail,bool test_base_path,bool (* thing_exists)(const string &))538 string datafile_path(string basename, bool croak_on_fail, bool test_base_path,
539                      bool (*thing_exists)(const string&))
540 {
541     basename = canonicalise_file_separator(basename);
542 
543     if (test_base_path && thing_exists(basename))
544         return basename;
545 
546     for (const string &basedir : _get_base_dirs())
547     {
548         string name = basedir + basename;
549 #ifdef __ANDROID__
550         __android_log_print(ANDROID_LOG_INFO,"Crawl","Looking for %s as '%s'",basename.c_str(),name.c_str());
551 #endif
552         if (thing_exists(name))
553             return name;
554     }
555 
556     // Die horribly.
557     if (croak_on_fail)
558     {
559         end(1, false, "Cannot find data file '%s' anywhere, aborting\n",
560             basename.c_str());
561     }
562 
563     return "";
564 }
565 
566 // Checks if directory 'dir' exists and tries to create it if it
567 // doesn't exist, modifying 'dir' to its canonical form.
568 //
569 // If given an empty 'dir', returns true without modifying 'dir' or
570 // performing any other checks.
571 //
572 // Otherwise, returns true if the directory already exists or was just
573 // created. 'dir' will be modified to a canonical representation,
574 // guaranteed to have the file separator appended to it, and with any
575 // / and \ separators replaced with the one true FILE_SEPARATOR.
576 //
check_mkdir(const string & whatdir,string * dir,bool silent)577 bool check_mkdir(const string &whatdir, string *dir, bool silent)
578 {
579     if (dir->empty())
580         return true;
581 
582     *dir = canonicalise_file_separator(*dir);
583 
584     // Suffix the separator if necessary
585     if ((*dir)[dir->length() - 1] != FILE_SEPARATOR)
586         *dir += FILE_SEPARATOR;
587 
588     if (!dir_exists(*dir) && !_create_dirs(*dir))
589     {
590         if (!silent)
591         {
592 #ifdef __ANDROID__
593             __android_log_print(ANDROID_LOG_INFO, "Crawl",
594                                 "%s \"%s\" does not exist and I can't create it.",
595                                 whatdir.c_str(), dir->c_str());
596 #endif
597             fprintf(stderr, "%s \"%s\" does not exist "
598                     "and I can't create it.\n",
599                     whatdir.c_str(), dir->c_str());
600         }
601         return false;
602     }
603 
604     return true;
605 }
606 
607 // Get the directory that contains save files for the current game
608 // type. This will not be the same as get_base_savedir() for game
609 // types such as Sprint.
_get_savefile_directory()610 static string _get_savefile_directory()
611 {
612     string dir = catpath(Options.save_dir, crawl_state.game_savedir_path());
613     check_mkdir("Save directory", &dir, false);
614     if (dir.empty())
615         dir = ".";
616     return dir;
617 }
618 
619 
620 /**
621  * Location of legacy ghost files. (The save directory.)
622  *
623  * @return The path to the directory for old ghost files.
624  */
_get_old_bonefile_directory()625 static string _get_old_bonefile_directory()
626 {
627     string dir = catpath(Options.shared_dir, crawl_state.game_savedir_path());
628     check_mkdir("Bones directory", &dir, false);
629     if (dir.empty())
630         dir = ".";
631     return dir;
632 }
633 
634 /**
635  * Location of ghost files.
636  *
637  * @return The path to the directory for ghost files.
638  */
_get_bonefile_directory()639 static string _get_bonefile_directory()
640 {
641     string dir = catpath(Options.shared_dir, crawl_state.game_savedir_path());
642     dir = catpath(dir, "bones");
643     check_mkdir("Bones directory", &dir, false);
644     if (dir.empty())
645         dir = ".";
646     return dir;
647 }
648 
649 // Returns a subdirectory of the current savefile directory as returned by
650 // _get_savefile_directory.
_get_savedir_path(const string & shortpath)651 static string _get_savedir_path(const string &shortpath)
652 {
653     return canonicalise_file_separator(
654         catpath(_get_savefile_directory(), shortpath));
655 }
656 
657 // Returns a subdirectory of the base save directory that contains all saves
658 // and cache directories. Save files for game type != GAME_TYPE_NORMAL may
659 // be found in a subdirectory of this dir. Use _get_savefile_directory() if
660 // you want the directory that contains save games for the current game
661 // type.
_get_base_savedir_path(const string & subpath="")662 static string _get_base_savedir_path(const string &subpath = "")
663 {
664     return canonicalise_file_separator(catpath(Options.save_dir, subpath));
665 }
666 
667 // Given a simple (relative) path, returns the path relative to the
668 // base save directory and a subdirectory named with the game version.
669 // This is useful when writing cache files and similar output that
670 // should not be shared between different game versions.
savedir_versioned_path(const string & shortpath)671 string savedir_versioned_path(const string &shortpath)
672 {
673 #ifdef VERSIONED_CACHE_DIR
674     const string versioned_dir =
675         _get_base_savedir_path(string("cache.") + Version::Long);
676 #else
677     const string versioned_dir = _get_base_savedir_path();
678 #endif
679     return catpath(versioned_dir, shortpath);
680 }
681 
682 #ifdef USE_TILE
683 #define LINEMAX 1024
_readln(chunk_reader & rd,char * buf)684 static bool _readln(chunk_reader &rd, char *buf)
685 {
686     for (int space = LINEMAX - 1; space; space--)
687     {
688         if (!rd.read(buf, 1))
689             return false;
690         if (*buf == '\n')
691             break;
692         buf++;
693     }
694     *buf = 0;
695     return true;
696 }
697 
_fill_player_doll(player_save_info & p,package * save)698 static void _fill_player_doll(player_save_info &p, package *save)
699 {
700     dolls_data equip_doll;
701     for (unsigned int j = 0; j < TILEP_PART_MAX; ++j)
702         equip_doll.parts[j] = TILEP_SHOW_EQUIP;
703 
704     equip_doll.parts[TILEP_PART_BASE]
705         = tilep_species_to_base_tile(p.species, p.experience_level);
706 
707     bool success = false;
708 
709     chunk_reader fdoll(save, "tdl");
710     {
711         char fbuf[LINEMAX];
712         if (_readln(fdoll,fbuf))
713         {
714             tilep_scan_parts(fbuf, equip_doll, p.species, p.experience_level);
715             tilep_race_default(p.species, p.experience_level, &equip_doll);
716             success = true;
717         }
718     }
719 
720     if (!success) // Use default doll instead.
721     {
722         job_type job = get_job_by_name(p.class_name.c_str());
723         if (job == JOB_UNKNOWN)
724             job = JOB_FIGHTER;
725 
726         tilep_job_default(job, &equip_doll);
727     }
728     p.doll = equip_doll;
729 }
730 #endif
731 
732 /*
733  * Returns a list of the names of characters that are already saved for the
734  * current user.
735  */
736 
_find_saved_characters()737 static vector<player_save_info> _find_saved_characters()
738 {
739     vector<player_save_info> chars;
740 
741     if (Options.no_save)
742         return chars;
743 
744 #ifndef DISABLE_SAVEGAME_LISTS
745     string searchpath = _get_savefile_directory();
746 
747     if (searchpath.empty())
748         searchpath = ".";
749 
750     for (const string &filename : get_dir_files_sorted(searchpath))
751     {
752         if (is_save_file_name(filename))
753         {
754             try
755             {
756                 package save(_get_savedir_path(filename).c_str(), false);
757                 player_save_info p = _read_character_info(&save);
758                 if (!p.name.empty())
759                 {
760                     p.filename = filename;
761 #ifdef USE_TILE
762                     if (Options.tile_menu_icons && save.has_chunk("tdl"))
763                         _fill_player_doll(p, &save);
764 #endif
765                     chars.push_back(p);
766                 }
767             }
768             catch (ext_fail_exception &E)
769             {
770                 dprf("%s: %s", filename.c_str(), E.what());
771             }
772             catch (game_ended_condition &E) // another process is using the save
773             {
774                 if (E.exit_reason != game_exit::abort)
775                     throw;
776             }
777         }
778     }
779 
780     sort(chars.begin(), chars.end());
781 #endif // !DISABLE_SAVEGAME_LISTS
782     return chars;
783 }
784 
find_all_saved_characters()785 vector<player_save_info> find_all_saved_characters()
786 {
787     set<string> dirs;
788     vector<player_save_info> saved_characters;
789     for (int i = 0; i < NUM_GAME_TYPE; ++i)
790     {
791         unwind_var<game_type> gt(
792             crawl_state.type,
793             static_cast<game_type>(i));
794 
795         const string savedir = _get_savefile_directory();
796         if (dirs.count(savedir))
797             continue;
798 
799         dirs.insert(savedir);
800 
801         vector<player_save_info> chars_in_dir = _find_saved_characters();
802         saved_characters.insert(saved_characters.end(),
803                                 chars_in_dir.begin(),
804                                 chars_in_dir.end());
805     }
806     return saved_characters;
807 }
808 
save_exists(const string & filename)809 bool save_exists(const string& filename)
810 {
811     return file_exists(_get_savefile_directory() + filename);
812 }
813 
get_savedir_filename(const string & name)814 string get_savedir_filename(const string &name)
815 {
816     return _get_savefile_directory() + get_save_filename(name);
817 }
818 
819 #define MAX_FILENAME_LENGTH 250
get_save_filename(const string & name)820 string get_save_filename(const string &name)
821 {
822     return chop_string(strip_filename_unsafe_chars(name), MAX_FILENAME_LENGTH,
823                        false) + SAVE_SUFFIX;
824 }
825 
_game_type_has_saves(const game_type g)826 static bool _game_type_has_saves(const game_type g)
827 {
828     // TODO: this may be useful elsewhere too?
829     switch (g)
830     {
831     case GAME_TYPE_ARENA:
832     case GAME_TYPE_HIGH_SCORES:
833     case GAME_TYPE_INSTRUCTIONS:
834     case GAME_TYPE_UNSPECIFIED:
835         return false;
836     default:
837         return true;
838     }
839 }
840 
_game_type_removed(const game_type g)841 static bool _game_type_removed(const game_type g)
842 {
843     return g == GAME_TYPE_ZOTDEF;
844 }
845 
_append_save_info(JsonWrapper & json,const char * filename,game_type intended_gt=NUM_GAME_TYPE)846 static bool _append_save_info(JsonWrapper &json, const char *filename,
847                                         game_type intended_gt=NUM_GAME_TYPE)
848 {
849     if (!file_exists(filename))
850         return false;
851     try
852     {
853         package save(filename, false);
854         player_save_info p = _read_character_info(&save);
855 
856         // TODO: some json for the non-loadable case? I think this comes up
857         // for save compat mismatches so shouldn't be relevant for webtiles
858         // except in case of bugs...
859         if (p.name.empty() || !p.save_loadable)
860             return false;
861 
862         auto *game_json = json_mkobject();
863 
864         // TODO: version info might be useful?
865         json_append_member(game_json, "loadable", json_mkbool(true));
866         json_append_member(game_json, "name", json_mkstring(p.name));
867         json_append_member(game_json, "game_type",
868             json_mkstring(gametype_to_str(p.saved_game_type)));
869         json_append_member(game_json, "short_desc",
870             json_mkstring(p.short_desc(false)));
871         json_append_member(game_json, "really_short_desc",
872             json_mkstring(p.really_short_desc()));
873 
874         // for the case where we are querying just one file, we don't have
875         // info on what the save slot is (if any -- could be an arbitrary
876         // file) so just use the file's value. This is really only here so
877         // that there is a consistent format to the json.
878         json_append_member(json.node, intended_gt == NUM_GAME_TYPE
879                                 ? gametype_to_str(p.saved_game_type).c_str()
880                                 : gametype_to_str(intended_gt).c_str(),
881                             game_json);
882         return true;
883     }
884     catch (game_ended_condition &E) // another process is using the save
885     {
886         if (E.exit_reason != game_exit::abort)
887             end(1); // something has gone fairly wrong in this case
888 
889         auto *game_json = json_mkobject();
890 
891         json_append_member(game_json, "loadable", json_mkbool(false));
892         json_append_member(game_json, "name", json_mkstring(""));
893         json_append_member(game_json, "game_type", json_mkstring(""));
894         json_append_member(game_json, "short_desc",
895                                                 json_mkstring("Save in use"));
896         json_append_member(game_json, "really_short_desc",
897                                                 json_mkstring(""));
898 
899         // May give "none" in the case of querying a save file by name
900         // that is currently in use.
901         json_append_member(json.node, gametype_to_str(intended_gt).c_str(),
902                                                                     game_json);
903         return true;
904     }
905 }
906 
_append_player_save_info(JsonWrapper & json,const char * name,game_type gt)907 static bool _append_player_save_info(JsonWrapper &json, const char *name, game_type gt)
908 {
909     // requires init file to have been read, otherwise the correct savedir
910     // paths may not have been initialized
911     unwind_var<game_type> temp_gt(crawl_state.type, gt);
912     return _append_save_info(json, get_savedir_filename(name).c_str(), gt);
913 }
914 
915 /**
916  * Print information about save files associated with `name` in JSON format.
917  * The JSON format is a map (JSON Object) from (saveable) game types to save
918  * information.
919  *
920  * If `name` is a filename, the map will have one element in it for just that
921  * file; if it is a player name, the map will have one entry for every
922  * game type that has a save. (Keep in mind that most game types share a single
923  * save slot.)
924  *
925  * If a save file is currently in use by some other process, it will get
926  * `loadable': false, as well as most other info missing. If a save is queried
927  * by filename and is in use, it will additionally be mapped from game type
928  * `none`.
929  */
print_save_json(const char * name)930 NORETURN void print_save_json(const char *name)
931 {
932     // TODO: The overall call is quite heavy. Can the overhead to get to this
933     // point be simplified at all? On my local machine it's about 80-100ms per
934     // call if things go well.
935     try
936     {
937         JsonWrapper json(json_mkobject());
938         // Check for the exact filename first, then go by char name.
939         // TODO: based on other CLOs, but maybe these shouldn't be collapsed
940         // into a single option?
941         if (file_exists(name))
942         {
943             if (!_append_save_info(json, name))
944             {
945                 fprintf(stderr, "Could not load '%s'\n", name);
946                 end(1);
947             }
948         }
949         else
950         {
951             // ugh. This is a heavy-handed way to ensure that the savedir
952             // option is set correctly on the first parse_args pass.
953             // TODO: test on dgl...
954             Options.reset_options();
955 
956             // treat `name` as a character name. Prints an empty json dict
957             // if this is wrong (or if the character has no saves).
958             // TODO: this code (and much other code) could be a lot smarter
959             // about shared save slots. (Everything but sprint shares just
960             // one slot...)
961             for (int i = 0; i < NUM_GAME_TYPE; ++i)
962             {
963                 auto gt = static_cast<game_type>(i);
964                 if (_game_type_has_saves(gt) && !_game_type_removed(gt))
965                     _append_player_save_info(json, name, gt);
966             }
967         }
968 
969         fprintf(stdout, "%s", json.to_string().c_str());
970         end(0);
971     }
972     catch (ext_fail_exception &fe)
973     {
974         fprintf(stderr, "Error: %s\n", fe.what());
975         end(1);
976     }
977 }
978 
get_prefs_filename()979 string get_prefs_filename()
980 {
981 #ifdef DGL_STARTUP_PREFS_BY_NAME
982     return _get_savefile_directory() + "start-"
983            + strip_filename_unsafe_chars(Options.game.name) + "-ns.prf";
984 #else
985     return _get_savefile_directory() + "start-ns.prf";
986 #endif
987 }
988 
write_ghost_version(writer & outf)989 void write_ghost_version(writer &outf)
990 {
991     // this may be distinct from the current save version
992     write_save_version(outf, save_version::current_bones());
993 
994     // extended_version just pads the version out to four 32-bit words.
995     // This makes the bones file compatible with Hearse with no extra
996     // munging needed.
997 
998     // Use a single signature 16-bit word to indicate that this is
999     // Stone Soup and to disambiguate this (unmunged) bones file
1000     // from the munged bones files offered by the old Crawl-aware
1001     // hearse.pl. Crawl-aware hearse.pl will prefix the bones file
1002     // with the first 16-bits of the Crawl version, and the following
1003     // 7 16-bit words set to 0.
1004     marshallShort(outf, GHOST_SIGNATURE);
1005 
1006     // Write the three remaining 32-bit words of padding.
1007     for (int i = 0; i < 3; ++i)
1008         marshallInt(outf, 0);
1009 }
1010 
_write_tagged_chunk(const string & chunkname,tag_type tag)1011 static void _write_tagged_chunk(const string &chunkname, tag_type tag)
1012 {
1013     writer outf(you.save, chunkname);
1014 
1015     write_save_version(outf, save_version::current());
1016     tag_write(tag, outf);
1017 }
1018 
_get_dest_stair_type(dungeon_feature_type stair_taken,bool & find_first)1019 static int _get_dest_stair_type(dungeon_feature_type stair_taken,
1020                                 bool &find_first)
1021 {
1022     // Order is important here.
1023     if (stair_taken == DNGN_EXIT_ABYSS)
1024     {
1025         find_first = false;
1026         return DNGN_EXIT_DUNGEON;
1027     }
1028 
1029     if (stair_taken == DNGN_EXIT_HELL)
1030         return DNGN_ENTER_HELL;
1031 
1032     if (stair_taken == DNGN_ENTER_HELL)
1033         return DNGN_EXIT_HELL;
1034 
1035     if (player_in_hell() && feat_is_stone_stair_down(stair_taken))
1036     {
1037         find_first = false;
1038         return DNGN_ENTER_HELL;
1039     }
1040 
1041     if (feat_is_stone_stair(stair_taken))
1042     {
1043         switch (stair_taken)
1044         {
1045         case DNGN_STONE_STAIRS_UP_I: return DNGN_STONE_STAIRS_DOWN_I;
1046         case DNGN_STONE_STAIRS_UP_II: return DNGN_STONE_STAIRS_DOWN_II;
1047         case DNGN_STONE_STAIRS_UP_III: return DNGN_STONE_STAIRS_DOWN_III;
1048 
1049         case DNGN_STONE_STAIRS_DOWN_I: return DNGN_STONE_STAIRS_UP_I;
1050         case DNGN_STONE_STAIRS_DOWN_II: return DNGN_STONE_STAIRS_UP_II;
1051         case DNGN_STONE_STAIRS_DOWN_III: return DNGN_STONE_STAIRS_UP_III;
1052 
1053         default: die("unknown stone stair %d", stair_taken);
1054         }
1055     }
1056 
1057     if (feat_is_escape_hatch(stair_taken) || stair_taken == DNGN_TRAP_SHAFT)
1058         return stair_taken;
1059 
1060     if (stair_taken == DNGN_ENTER_DIS
1061         || stair_taken == DNGN_ENTER_GEHENNA
1062         || stair_taken == DNGN_ENTER_COCYTUS
1063         || stair_taken == DNGN_ENTER_TARTARUS)
1064     {
1065         return player_in_hell() ? DNGN_ENTER_HELL : stair_taken;
1066     }
1067 
1068     if (feat_is_branch_exit(stair_taken))
1069     {
1070         for (branch_iterator it; it; ++it)
1071             if (it->exit_stairs == stair_taken)
1072                 return it->entry_stairs;
1073         die("entrance corresponding to exit %d not found", stair_taken);
1074     }
1075 
1076     if (feat_is_branch_entrance(stair_taken))
1077     {
1078         for (branch_iterator it; it; ++it)
1079             if (it->entry_stairs == stair_taken)
1080                 return it->exit_stairs;
1081         die("return corresponding to entry %d not found", stair_taken);
1082     }
1083 #if TAG_MAJOR_VERSION == 34
1084     if (stair_taken == DNGN_ENTER_LABYRINTH)
1085     {
1086         // dgn_find_nearby_stair uses special logic for labyrinths.
1087         return DNGN_ENTER_LABYRINTH;
1088     }
1089 #endif
1090 
1091     if (feat_is_portal_entrance(stair_taken))
1092         return DNGN_STONE_ARCH;
1093 
1094     // Note: stair_taken can equal things like DNGN_FLOOR
1095     // Just find a nice empty square.
1096     find_first = false;
1097     return DNGN_FLOOR;
1098 }
1099 
_place_player_on_stair(int stair_taken,const coord_def & dest_pos,const string & hatch_name)1100 static void _place_player_on_stair(int stair_taken, const coord_def& dest_pos,
1101                                    const string &hatch_name)
1102 
1103 {
1104     bool find_first = true;
1105     dungeon_feature_type stair_type = static_cast<dungeon_feature_type>(
1106             _get_dest_stair_type(static_cast<dungeon_feature_type>(stair_taken),
1107                                  find_first));
1108 
1109     you.moveto(dgn_find_nearby_stair(stair_type, dest_pos, find_first,
1110                                      hatch_name));
1111 }
1112 
_clear_env_map()1113 static void _clear_env_map()
1114 {
1115     env.map_knowledge.init(map_cell());
1116     env.map_forgotten.reset();
1117 }
1118 
_grab_follower_at(const coord_def & pos,bool can_follow)1119 static bool _grab_follower_at(const coord_def &pos, bool can_follow)
1120 {
1121     if (pos == you.pos())
1122         return false;
1123 
1124     monster* fol = monster_at(pos);
1125     if (!fol || !fol->alive() || fol->incapacitated())
1126         return false;
1127 
1128     // only H's ancestors can follow into portals & similar.
1129     if (!can_follow && !mons_is_hepliaklqana_ancestor(fol->type))
1130         return false;
1131 
1132     // The monster has to already be tagged in order to follow.
1133     if (!testbits(fol->flags, MF_TAKING_STAIRS))
1134         return false;
1135 
1136     // If a monster that can't use stairs was marked as a follower,
1137     // it's because it's an ally and there might be another ally
1138     // behind it that might want to push through.
1139     // This means we don't actually send it on transit, but we do
1140     // return true, so adjacent real followers are handled correctly. (jpeg)
1141     if (!mons_can_use_stairs(*fol))
1142         return true;
1143 
1144     level_id dest = level_id::current();
1145 
1146     dprf("%s is following to %s.", fol->name(DESC_THE, true).c_str(),
1147          dest.describe().c_str());
1148     bool could_see = you.can_see(*fol);
1149     fol->set_transit(dest);
1150     fol->destroy_inventory();
1151     monster_cleanup(fol);
1152     if (could_see)
1153         view_update_at(pos);
1154     return true;
1155 }
1156 
_grab_followers()1157 static void _grab_followers()
1158 {
1159     const bool can_follow = branch_allows_followers(you.where_are_you);
1160 
1161     int non_stair_using_allies = 0;
1162     int non_stair_using_summons = 0;
1163 
1164     monster* dowan = nullptr;
1165     monster* duvessa = nullptr;
1166 
1167     // Handle some hacky cases
1168     for (adjacent_iterator ai(you.pos()); ai; ++ai)
1169     {
1170         monster* fol = monster_at(*ai);
1171         if (fol == nullptr)
1172             continue;
1173 
1174         if (mons_is_mons_class(fol, MONS_DUVESSA) && fol->alive())
1175             duvessa = fol;
1176 
1177         if (mons_is_mons_class(fol, MONS_DOWAN) && fol->alive())
1178             dowan = fol;
1179 
1180         if (fol->wont_attack() && !mons_can_use_stairs(*fol))
1181         {
1182             non_stair_using_allies++;
1183             // If the class can normally use stairs it
1184             // must have been a summon
1185             if (mons_class_can_use_stairs(fol->type))
1186                 non_stair_using_summons++;
1187         }
1188     }
1189 
1190     // Deal with Dowan and Duvessa here.
1191     if (dowan && duvessa)
1192     {
1193         if (!testbits(dowan->flags, MF_TAKING_STAIRS)
1194             || !testbits(duvessa->flags, MF_TAKING_STAIRS))
1195         {
1196             dowan->flags &= ~MF_TAKING_STAIRS;
1197             duvessa->flags &= ~MF_TAKING_STAIRS;
1198         }
1199     }
1200     else if (dowan && !duvessa)
1201     {
1202         if (!dowan->props.exists("can_climb"))
1203             dowan->flags &= ~MF_TAKING_STAIRS;
1204     }
1205     else if (!dowan && duvessa)
1206     {
1207         if (!duvessa->props.exists("can_climb"))
1208             duvessa->flags &= ~MF_TAKING_STAIRS;
1209     }
1210 
1211     if (can_follow && non_stair_using_allies > 0)
1212     {
1213         // Summons won't follow and will time out.
1214         if (non_stair_using_summons > 0)
1215         {
1216             mprf("Your summoned %s left behind.",
1217                  non_stair_using_allies > 1 ? "allies are" : "ally is");
1218         }
1219         else
1220         {
1221             // Permanent undead are left behind but stay.
1222             mprf("Your mindless thrall%s behind.",
1223                  non_stair_using_allies > 1 ? "s stay" : " stays");
1224         }
1225     }
1226 
1227     bool visited[GXM][GYM];
1228     memset(&visited, 0, sizeof(visited));
1229 
1230     vector<coord_def> places[2] = { { you.pos() }, {} };
1231     int place_set = 0;
1232     while (!places[place_set].empty())
1233     {
1234         for (const coord_def &p : places[place_set])
1235         {
1236             for (adjacent_iterator ai(p); ai; ++ai)
1237             {
1238                 if (visited[ai->x][ai->y])
1239                     continue;
1240 
1241                 visited[ai->x][ai->y] = true;
1242                 if (_grab_follower_at(*ai, can_follow))
1243                     places[!place_set].push_back(*ai);
1244             }
1245         }
1246         places[place_set].clear();
1247         place_set = !place_set;
1248     }
1249 
1250     // Clear flags of monsters that didn't follow.
1251     for (auto &mons : menv_real)
1252     {
1253         if (!mons.alive())
1254             continue;
1255         if (mons.type == MONS_BATTLESPHERE)
1256             end_battlesphere(&mons, false);
1257         if (mons.type == MONS_SPECTRAL_WEAPON)
1258             end_spectral_weapon(&mons, false);
1259         mons.flags &= ~MF_TAKING_STAIRS;
1260     }
1261 }
1262 
_do_lost_monsters()1263 static void _do_lost_monsters()
1264 {
1265     // Uniques can be considered wandering Pan just like you, so they're not
1266     // gone forever. The likes of Cerebov won't be generated elsewhere, but
1267     // there's no need to special-case that.
1268     if (player_in_branch(BRANCH_PANDEMONIUM))
1269         for (monster_iterator mi; mi; ++mi)
1270             if (mons_is_unique(mi->type) && !(mi->flags & MF_TAKING_STAIRS))
1271                 you.unique_creatures.set(mi->type, false);
1272 }
1273 
1274 // Should be called after _grab_followers(), so that items carried by
1275 // followers won't be considered lost.
_do_lost_items()1276 static void _do_lost_items()
1277 {
1278     for (const auto &item : env.item)
1279         if (item.defined() && item.pos != ITEM_IN_INVENTORY)
1280             item_was_lost(item);
1281 }
1282 
1283 /**
1284  * Perform cleanup when leaving a level.
1285  *
1286  * If returning to the previous level on the level stack (e.g. when leaving the
1287  * abyss), pop it off the stack. Delete non-permanent levels. Also check to be
1288  * sure no loops have formed in the level stack, and, for Fedhasites, rots any
1289  * corpses left behind.
1290  *
1291  * @param stair_taken   The means used to leave the last level.
1292  * @param old_level     The ID of the previous level.
1293  * @param return_pos    Set to the level entrance, if popping a stack level.
1294  * @return Whether the level was popped onto the stack.
1295  */
_leave_level(dungeon_feature_type stair_taken,const level_id & old_level,coord_def * return_pos)1296 static bool _leave_level(dungeon_feature_type stair_taken,
1297                          const level_id& old_level, coord_def *return_pos)
1298 {
1299     bool popped = false;
1300 
1301     if (!you.level_stack.empty()
1302         && you.level_stack.back().id == level_id::current())
1303     {
1304         *return_pos = you.level_stack.back().pos;
1305         you.level_stack.pop_back();
1306         env.level_state |= LSTATE_DELETED;
1307         popped = true;
1308     }
1309     else if (stair_taken == DNGN_TRANSIT_PANDEMONIUM
1310              || stair_taken == DNGN_EXIT_THROUGH_ABYSS
1311              || stair_taken == DNGN_STONE_STAIRS_DOWN_I
1312              && old_level.branch == BRANCH_ZIGGURAT
1313              || old_level.branch == BRANCH_ABYSS)
1314     {
1315         env.level_state |= LSTATE_DELETED;
1316     }
1317 
1318     if (is_level_on_stack(level_id::current())
1319         && !player_in_branch(BRANCH_ABYSS))
1320     {
1321         vector<string> stack;
1322         for (level_pos lvl : you.level_stack)
1323             stack.push_back(lvl.id.describe());
1324         if (you.wizard)
1325         {
1326             // warn about breakage so testers know it's an abnormal situation.
1327             mprf(MSGCH_ERROR, "Error: you smelly wizard, how dare you enter "
1328                  "the same level (%s) twice! It will be trampled upon return.\n"
1329                  "The stack has: %s.",
1330                  level_id::current().describe().c_str(),
1331                  comma_separated_line(stack.begin(), stack.end(),
1332                                       ", ", ", ").c_str());
1333         }
1334         else
1335         {
1336             die("Attempt to enter a portal (%s) twice; stack: %s",
1337                 level_id::current().describe().c_str(),
1338                 comma_separated_line(stack.begin(), stack.end(),
1339                                      ", ", ", ").c_str());
1340         }
1341     }
1342 
1343     return popped;
1344 }
1345 
1346 /**
1347  * Move the player to the appropriate entrance location in a level.
1348  *
1349  * @param stair_taken   The means used to leave the last level.
1350  * @param return_pos    The location of the entrance portal, if applicable.
1351  * @param dest_pos      The player's location on the last level.
1352  */
_place_player(dungeon_feature_type stair_taken,const coord_def & return_pos,const coord_def & dest_pos,const string & hatch_name)1353 static void _place_player(dungeon_feature_type stair_taken,
1354                           const coord_def &return_pos,
1355                           const coord_def &dest_pos, const string &hatch_name)
1356 {
1357     if (player_in_branch(BRANCH_ABYSS))
1358         you.moveto(ABYSS_CENTRE);
1359     else if (!return_pos.origin())
1360         you.moveto(return_pos);
1361     else
1362         _place_player_on_stair(stair_taken, dest_pos, hatch_name);
1363 
1364     // Don't return the player into walls, deep water, or a trap.
1365     for (distance_iterator di(you.pos(), true, false); di; ++di)
1366         if (you.is_habitable_feat(env.grid(*di))
1367             && !is_feat_dangerous(env.grid(*di), true)
1368             && !feat_is_trap(env.grid(*di)))
1369         {
1370             if (you.pos() != *di)
1371                 you.moveto(*di);
1372             break;
1373         }
1374 
1375     // This should fix the "monster occurring under the player" bug.
1376     monster *mon = monster_at(you.pos());
1377     if (mon && !fedhas_passthrough(mon))
1378     {
1379         for (distance_iterator di(you.pos()); di; ++di)
1380         {
1381             if (!monster_at(*di) && mon->is_habitable(*di))
1382             {
1383                 mon->move_to_pos(*di);
1384                 return;
1385             }
1386         }
1387 
1388         dprf("%s under player and can't be moved anywhere; killing",
1389              mon->name(DESC_PLAIN).c_str());
1390         monster_die(*mon, KILL_DISMISSED, NON_MONSTER);
1391         // XXX: do we need special handling for uniques...?
1392     }
1393 }
1394 
1395 // Update the trackers after the player changed level.
trackers_init_new_level()1396 void trackers_init_new_level()
1397 {
1398     travel_init_new_level();
1399 }
1400 
_get_hatch_name()1401 static string _get_hatch_name()
1402 {
1403     vector <map_marker *> markers;
1404     markers = find_markers_by_prop(HATCH_NAME_PROP);
1405     for (auto m : markers)
1406     {
1407         if (m->pos == you.pos())
1408         {
1409             string name = m->property(HATCH_NAME_PROP);
1410             ASSERT(!name.empty());
1411             return name;
1412         }
1413     }
1414     return "";
1415 }
1416 
1417 static const string VISITED_LEVELS_KEY = "visited_levels";
1418 
1419 #if TAG_MAJOR_VERSION == 34
1420 // n.b. these functions are in files.cc largely because this is where the fixup
1421 // needs to happen.
1422 // before pregeneration, whether the level had been visited was synonymous with
1423 // whether it had been visited, but after, we need to track this information
1424 // more directly. It is also inferrable from turns_on_level, but you can't get
1425 // at that very easily without fully loading the level.
1426 // no need for a minor version here, though there will be a brief window of
1427 // offline pregen games that this doesn't handle right -- they will get things
1428 // like broken runelock. (In principle this fixup could be done by loading
1429 // each level and checking turns, but it's not worth the trouble for these few
1430 // games.)
_fixup_visited_from_package()1431 static void _fixup_visited_from_package()
1432 {
1433     // for games started later than this fixup, this prop is initialized in
1434     // player::player
1435     CrawlHashTable &visited = you.props[VISITED_LEVELS_KEY].get_table();
1436     if (visited.size()) // only 0 for upgrades, or before entering D:1
1437         return;
1438     vector<level_id> levels = all_dungeon_ids();
1439     for (const level_id &lid : levels)
1440         if (is_existing_level(lid))
1441             visited[lid.describe()] = true;
1442 }
1443 #endif
1444 
set_level_visited(const level_id & level)1445 void player::set_level_visited(const level_id &level)
1446 {
1447     auto &visited = props[VISITED_LEVELS_KEY].get_table();
1448     visited[level.describe()] = true;
1449 }
1450 
1451 /**
1452  * Has the player visited the level currently stored in the save under the id
1453  * `level`, if there is one? Returns false if there isn't one. This stores
1454  * *token level* visited state, not type-level -- it does not answer questions
1455  * like, e.g. has the player ever visited a trove? For that, see place_info.
1456  * This distinction matters mainly for portal branches, especially ones that can
1457  * be revisited, e.g. Pan levels and zigs.
1458  */
level_visited(const level_id & level)1459 bool player::level_visited(const level_id &level)
1460 {
1461     // `is_existing_level` is not reliable after the game end, because the
1462     // save no longer exists, so we ignore it for printing morgues
1463     if (!is_existing_level(level) && you.save)
1464         return false;
1465     const auto &visited = props[VISITED_LEVELS_KEY].get_table();
1466     return visited.exists(level.describe());
1467 }
1468 
_generic_level_reset()1469 static void _generic_level_reset()
1470 {
1471     // TODO: can more be pulled into here?
1472 
1473     you.prev_targ = MHITNOT;
1474     you.prev_grd_targ.reset();
1475 
1476     // Lose all listeners.
1477     dungeon_events.clear();
1478     clear_travel_trail();
1479 }
1480 
1481 
1482 // used to resolve generation order for cases where a single level has multiple
1483 // portals. This currently should only include portals that can appear at most
1484 // once.
1485 static const vector<branch_type> portal_generation_order =
1486 {
1487     BRANCH_SEWER,
1488     BRANCH_OSSUARY,
1489     BRANCH_ICE_CAVE,
1490     BRANCH_VOLCANO,
1491     BRANCH_BAILEY,
1492     BRANCH_GAUNTLET,
1493 #if TAG_MAJOR_VERSION == 34
1494     BRANCH_LABYRINTH,
1495 #endif
1496     // do not pregenerate bazaar (TODO: this is non-ideal)
1497     // do not pregenerate trove
1498     BRANCH_WIZLAB,
1499     BRANCH_DESOLATION,
1500 };
1501 
update_portal_entrances()1502 void update_portal_entrances()
1503 {
1504     unordered_set<branch_type, std::hash<int>> seen_portals;
1505     auto const cur_level = level_id::current();
1506     // add any portals not currently registered
1507     for (rectangle_iterator ri(0); ri; ++ri)
1508     {
1509         dungeon_feature_type feat = env.grid(*ri);
1510         // excludes pan, hell, abyss.
1511         if (feat_is_portal_entrance(feat) && !feature_mimic_at(*ri))
1512         {
1513             level_id whither = stair_destination(feat, "", false);
1514             if (whither.branch == BRANCH_ZIGGURAT // not (quite) pregenerated
1515                 || whither.branch == BRANCH_TROVE // not pregenerated
1516                 || whither.branch == BRANCH_BAZAAR) // multiple bazaars possible
1517             {
1518                 continue; // handle these differently
1519             }
1520             dprf("Setting up entry for %s.", whither.describe().c_str());
1521             ASSERT(count(portal_generation_order.begin(),
1522                          portal_generation_order.end(),
1523                          whither.branch) == 1);
1524             if (brentry[whither.branch] != level_id())
1525             {
1526                 mprf(MSGCH_ERROR, "Second portal entrance for %s!",
1527                     whither.describe().c_str());
1528             }
1529             brentry[whither.branch] = cur_level;
1530             seen_portals.insert(whither.branch);
1531         }
1532     }
1533     // clean up any portals that aren't actually here -- comes up for wizmode
1534     // and test mode cases.
1535     for (auto b : portal_generation_order)
1536         if (!seen_portals.count(b) && brentry[b] == cur_level)
1537             brentry[b] = level_id();
1538 }
1539 
reset_portal_entrances()1540 void reset_portal_entrances()
1541 {
1542     for (auto b : portal_generation_order)
1543         if (brentry[b].is_valid())
1544             brentry[b] = level_id();
1545 }
1546 
1547 /**
1548  * Generate portals relative to the current level. This function does not clean
1549  * up builder state.
1550  *
1551  * @return the number of levels that generated, or -1 if the builder failed.
1552  */
_generate_portal_levels()1553 static int _generate_portal_levels()
1554 {
1555     // find any portals that branch off of the current level.
1556     level_id here = level_id::current();
1557     vector<level_id> to_build;
1558     for (auto b : portal_generation_order)
1559         if (brentry[b] == here)
1560             for (int i = 1; i <= brdepth[b]; i++)
1561                 to_build.push_back(level_id(b, i));
1562 
1563     int count = 0;
1564     for (auto lid : to_build)
1565     {
1566         if (!generate_level(lid))
1567         {
1568             // Should this crash? Reaching this case means that multiple
1569             // entrances to a non-reusable portal generated.
1570             if (you.save->has_chunk(lid.describe()))
1571                 mprf(MSGCH_ERROR, "Portal %s already exists!", lid.describe().c_str());
1572             else
1573                 return -1;
1574         }
1575         count++;
1576     }
1577     return count;
1578 }
1579 
1580 /**
1581  * Ensure that the level given by `l` is generated. This does not do much in
1582  * the way of cleanup, and the caller must ensure the player ends up somewhere
1583  * sensible afterwards (this will not place the player, and will wipe out their
1584  * current location state if a level is built). Does not do anything if the
1585  * save already contains the relevant level.
1586  *
1587  * This function may generate multiple levels: any necessary portal levels
1588  * needed for `l` are built also.
1589  *
1590  * @param l the level to try to build.
1591  * @return whether the required builder steps succeeded, if there are any;
1592  * false means that either there was a builder error, or the level already
1593  * exists. This can be checked by looking at whether the save chunk exists.
1594  */
generate_level(const level_id & l)1595 bool generate_level(const level_id &l)
1596 {
1597     const string level_name = l.describe();
1598     if (you.save->has_chunk(level_name))
1599         return false;
1600 
1601     unwind_var<int> you_depth(you.depth, l.depth);
1602     unwind_var<branch_type> you_branch(you.where_are_you, l.branch);
1603     unwind_var<coord_def> you_saved_position(you.position);
1604     you.position.reset();
1605 
1606     // simulate a reasonable stair to enter the level with
1607     const dungeon_feature_type stair_taken =
1608           you.depth == 1
1609         ? (you.where_are_you == BRANCH_DUNGEON
1610            ? DNGN_UNSEEN
1611            : branches[you.where_are_you].entry_stairs)
1612         : DNGN_STONE_STAIRS_DOWN_I;
1613 
1614     unwind_var<dungeon_feature_type> stair(you.transit_stair, stair_taken);
1615     // TODO how necessary is this?
1616     unwind_bool ylev(you.entering_level, true);
1617     // n.b. crawl_state.generating_level is handled in builder
1618 
1619     _generic_level_reset();
1620     delete_all_clouds();
1621     los_changed(); // invalidate the los cache, which impacts monster placement
1622 
1623     // initialize env for builder
1624     env.turns_on_level = -1;
1625     tile_init_default_flavour();
1626     tile_clear_flavour();
1627     tile_env.names.clear();
1628     _clear_env_map();
1629 
1630     // finally -- everything is set up, call the builder.
1631     dprf("Generating new level for '%s'.", level_name.c_str());
1632     if (!builder(true))
1633         return false;
1634 
1635     auto &vault_list =  you.vault_list[level_id::current()];
1636 #ifdef DEBUG
1637     // places where a level can generate multiple times.
1638     // could add portals to this list for debugging purposes?
1639     if (   you.where_are_you == BRANCH_ABYSS
1640         || you.where_are_you == BRANCH_PANDEMONIUM
1641         || you.where_are_you == BRANCH_BAZAAR
1642         || you.where_are_you == BRANCH_ZIGGURAT)
1643     {
1644         vault_list.push_back("[gen]");
1645     }
1646 #endif
1647     const auto &level_vaults = level_vault_names();
1648     vault_list.insert(vault_list.end(),
1649                         level_vaults.begin(), level_vaults.end());
1650 
1651     // initialize env for a new level
1652     env.turns_on_level = 0;
1653     env.sanctuary_pos  = coord_def(-1, -1);
1654     env.sanctuary_time = 0;
1655     env.markers.init_all(); // init first, activation happens when entering
1656     show_update_emphasis(); // Clear map knowledge stair emphasis in env.
1657     update_portal_entrances();
1658 
1659     // save the level and associated env state
1660     save_level(level_id::current());
1661 
1662     const string save_name = level_id::current().describe(); // should be same as level_name...
1663 
1664     // generate levels for all portals that branch off from here
1665     int portal_level_count = _generate_portal_levels();
1666     if (portal_level_count == -1)
1667         return false; // something failed, bail immediately
1668     else if (portal_level_count > 0)
1669     {
1670         // if portals were generated, we're currently elsewhere. Switch back to
1671         // the level generated before the portals.
1672         ASSERT(you.save->has_chunk(save_name));
1673         dprf("Reloading new level '%s'.", save_name.c_str());
1674         _restore_tagged_chunk(you.save, save_name, TAG_LEVEL,
1675             "Level file is invalid.");
1676     }
1677     // Did the generation process actually manage to place the player? This is
1678     // a useful sanity check, and also is necessary for the initial loading
1679     // process.
1680     you.on_current_level = (you_depth.original_value() == l.depth
1681                             && you_branch.original_value() == l.branch);
1682     return true;
1683 }
1684 
1685 // bel's original proposal generated D to lair depth, then lair, then D
1686 // to orc depth, then orc, then the rest of D. I have simplified this to
1687 // just generate whole branches at a time -- I am not sure how much real
1688 // impact this has, though it does mean a pregen popup when the player enters
1689 // lair, typically.
1690 //
1691 // Portals are handled via `portal_generation_order`, and generated as-needed
1692 // with the level they appear on.
1693 //
1694 // We generate temple first so as to save the player a popup when they find it
1695 // in mid-dungeon; it's fully decided in game setup and shouldn't interact with
1696 // rng for other branches anyways.
1697 //
1698 // How should this relate to logical_branch_order etc?
1699 static const vector<branch_type> branch_generation_order =
1700 {
1701     BRANCH_TEMPLE,
1702     BRANCH_DUNGEON,
1703     BRANCH_LAIR,
1704     BRANCH_ORC,
1705     BRANCH_SPIDER,
1706     BRANCH_SNAKE,
1707     BRANCH_SHOALS,
1708     BRANCH_SWAMP,
1709     BRANCH_VAULTS,
1710     BRANCH_CRYPT,
1711     BRANCH_DEPTHS,
1712     BRANCH_VESTIBULE,
1713     BRANCH_ELF,
1714     BRANCH_ZOT,
1715     BRANCH_SLIME,
1716     BRANCH_TOMB,
1717     BRANCH_TARTARUS,
1718     BRANCH_COCYTUS,
1719     BRANCH_DIS,
1720     BRANCH_GEHENNA,
1721     BRANCH_PANDEMONIUM,
1722     BRANCH_ZIGGURAT,
1723     NUM_BRANCHES,
1724 };
1725 
_branch_pregenerates(branch_type b)1726 static bool _branch_pregenerates(branch_type b)
1727 {
1728     if (!you.deterministic_levelgen)
1729         return false;
1730     if (b == NUM_BRANCHES || !brentry[b].is_valid() && is_random_subbranch(b))
1731         return false;
1732     return count(branch_generation_order.begin(),
1733         branch_generation_order.end(), b) > 0;
1734 }
1735 
1736 /**
1737 * Generate dungeon branches in a stable order until the level `stopping_point`
1738 * is found; `stopping_point` will be generated if it doesn't already exist. If
1739 * it does exist, the function is a noop.
1740 *
1741 * If `stopping_point` is not in the generation order, it will be generated on
1742 * its own.
1743 *
1744 * To generate all generatable levels, pass a level_id with NUM_BRANCHES as the
1745 * branch.
1746 *
1747 * @return whether stopping_point generated; if stopping_point is NUM_BRANCHES,
1748 * whether the full pregen list completed. This will return false if all needed
1749 * levels are already generated, so the caller should check whether false is an
1750 * error case or trivial success (using the save chunk).
1751 */
pregen_dungeon(const level_id & stopping_point)1752 bool pregen_dungeon(const level_id &stopping_point)
1753 {
1754     // TODO: the is_valid() check here doesn't look quite right to me, but so
1755     // far I can't get it to break anything...
1756     if (stopping_point.is_valid()
1757         || stopping_point.branch != NUM_BRANCHES &&
1758            is_random_subbranch(stopping_point.branch) && you.wizard)
1759     {
1760         if (you.save->has_chunk(stopping_point.describe()))
1761             return false;
1762 
1763         if (!_branch_pregenerates(stopping_point.branch))
1764             return generate_level(stopping_point);
1765     }
1766 
1767     vector<level_id> to_generate;
1768     bool at_end = false;
1769     for (auto br : branch_generation_order)
1770     {
1771         if (br == BRANCH_ZIGGURAT &&
1772             stopping_point.branch == BRANCH_ZIGGURAT)
1773         {
1774             // zigs delete levels as they go, so don't catchup when we're
1775             // already in one. Zigs are only handled this way so that everything
1776             // else generates first.
1777             to_generate.push_back(stopping_point);
1778             continue;
1779         }
1780         // TODO: why is dungeon invalid? it's not set up properly in
1781         // `initialise_branch_depths` for some reason. The vestibule is invalid
1782         // because its depth isn't set until the player actually enters a
1783         // portal, similarly for other portal branches.
1784         if (br < NUM_BRANCHES &&
1785             (brentry[br].is_valid()
1786              || br == BRANCH_DUNGEON || br == BRANCH_VESTIBULE
1787              || !is_connected_branch(br)))
1788         {
1789             for (int i = 1; i <= brdepth[br]; i++)
1790             {
1791                 level_id new_level = level_id(br, i);
1792                 // skip any levels that have already generated.
1793                 if (you.save->has_chunk(new_level.describe()))
1794                     continue;
1795                 to_generate.push_back(new_level);
1796 
1797                 if (br == stopping_point.branch
1798                     && (i == stopping_point.depth || i == brdepth[br]))
1799                 {
1800                     at_end = true;
1801                     break;
1802                 }
1803             }
1804         }
1805         if (at_end)
1806             break;
1807     }
1808 
1809     if (to_generate.size() == 0)
1810     {
1811         dprf("levelgen: No valid levels to generate.");
1812         return false;
1813     }
1814     // TODO: some levels are very slow (typically in depths), and a popup might
1815     // be helpful to the player. But is there a good way to tell?
1816     else if (to_generate.size() == 1)
1817         return generate_level(to_generate[0]); // no popup for this case
1818     else
1819     {
1820         // be sure that AK start doesn't interfere with the builder
1821         unwind_var<game_chapter> chapter(you.chapter, CHAPTER_ORB_HUNTING);
1822 
1823         ui::progress_popup progress("Generating dungeon...\n\n", 35);
1824         progress.advance_progress();
1825 
1826         for (const level_id &new_level : to_generate)
1827         {
1828             string status = "\nbuilding ";
1829 
1830             switch (new_level.branch)
1831             {
1832             case BRANCH_SPIDER:
1833             case BRANCH_SNAKE:
1834                 status += "a lair branch";
1835                 break;
1836             case BRANCH_SHOALS:
1837             case BRANCH_SWAMP:
1838                 status += "another lair branch";
1839                 break;
1840             default:
1841                 status += branches[new_level.branch].longname;
1842                 break;
1843             }
1844             progress.set_status_text(status);
1845             dprf("Pregenerating %s:%d",
1846                 branches[new_level.branch].abbrevname, new_level.depth);
1847             progress.advance_progress();
1848 
1849             // (save chunk existence is checked above, so isn't relevant here)
1850             if (!generate_level(new_level))
1851                 return false; // level failed to generate -- bail immediately
1852         }
1853 
1854         return true;
1855     }
1856 }
1857 
_rescue_player_from_wall()1858 static void _rescue_player_from_wall()
1859 {
1860     // n.b. you.wizmode_teleported_into_rock would be better, but it is not
1861     // actually saved.
1862     if (cell_is_solid(you.pos()) && !you.wizard)
1863     {
1864         // if the player has somehow gotten into a wall, there may have been
1865         // a fairly non-trivial crash, putting the player at some arbitrary
1866         // position relative to where they were. Rescue them by trying to find
1867         // a seen staircase, with a clear space near the wall as just a
1868         // a fallback.
1869         mprf(MSGCH_ERROR, "Emergency fixup: removing player from wall "
1870                           "at %d,%d. Please report this as a bug!",
1871                           you.pos().x, you.pos().y);
1872         vector<coord_def> upstairs;
1873         vector<coord_def> downstairs;
1874         coord_def backup_clear_pos(-1,-1);
1875         for (distance_iterator di(you.pos()); di; ++di)
1876         {
1877             // just find any clear square as a backup for really weird cases.
1878             if (!in_bounds(backup_clear_pos) && !cell_is_solid(*di))
1879                 backup_clear_pos = *di;
1880             // TODO: in principle this should use env.map_forgotten if it
1881             // exists, but I'm not sure that is worth the trouble.
1882             if (feat_is_stair(env.grid(*di)) && env.map_seen(*di))
1883             {
1884                 const command_type dir = feat_stair_direction(env.grid(*di));
1885                 if (dir == CMD_GO_UPSTAIRS)
1886                     upstairs.push_back(*di);
1887                 else if (dir == CMD_GO_DOWNSTAIRS)
1888                     downstairs.push_back(*di);
1889             }
1890         }
1891         coord_def target = backup_clear_pos;
1892         if (upstairs.size())
1893             target = upstairs[0];
1894         else if (downstairs.size())
1895             target = downstairs[0];
1896         if (!in_bounds(target) && player_in_branch(BRANCH_ABYSS))
1897         {
1898             // something is *seriously* messed up. This can happen if the game
1899             // crashed on an AK start where the initial map wasn't saved.
1900             // Because it is abyss, it is relatively safe to just move a player
1901             // to an arbitrary point and let abyss shift take over. (AK starts,
1902             // the main case, can also escape from the abyss at this point.)
1903             const coord_def emergency(1,1);
1904             env.grid(emergency) = DNGN_FLOOR;
1905             target = emergency;
1906         }
1907         // if things get this messed up, don't make them worse
1908         ASSERT(in_bounds(target));
1909         you.moveto(target);
1910     }
1911 }
1912 
1913 /**
1914  * Load the current level.
1915  *
1916  * @param stair_taken   The means used to enter the level.
1917  * @param load_mode     Whether the level is being entered, examined, etc.
1918  * @return Whether a new level was created.
1919  */
load_level(dungeon_feature_type stair_taken,load_mode_type load_mode,const level_id & old_level)1920 bool load_level(dungeon_feature_type stair_taken, load_mode_type load_mode,
1921                 const level_id& old_level)
1922 {
1923     const string level_name = level_id::current().describe();
1924     if (!you.save->has_chunk(level_name) && load_mode == LOAD_VISITOR)
1925         return false;
1926 
1927     const bool make_changes =
1928         (load_mode == LOAD_START_GAME || load_mode == LOAD_ENTER_LEVEL);
1929 
1930 #if TAG_MAJOR_VERSION == 34
1931     // fixup saves that don't have this prop initialized.
1932     if (load_mode == LOAD_RESTART_GAME)
1933         _fixup_visited_from_package();
1934 #endif
1935 
1936     // Did we get here by popping the level stack?
1937     bool popped = false;
1938 
1939     coord_def return_pos; //TODO: initialize to null
1940 
1941     string hatch_name = "";
1942     if (feat_is_escape_hatch(stair_taken))
1943         hatch_name = _get_hatch_name();
1944 
1945     if (load_mode != LOAD_VISITOR)
1946         popped = _leave_level(stair_taken, old_level, &return_pos);
1947 
1948     unwind_var<dungeon_feature_type> stair(
1949         you.transit_stair, stair_taken, DNGN_UNSEEN);
1950     unwind_bool ylev(you.entering_level, load_mode != LOAD_VISITOR, false);
1951 
1952 #ifdef DEBUG_LEVEL_LOAD
1953     mprf(MSGCH_DIAGNOSTICS, "Loading... branch: %d, level: %d",
1954                             you.where_are_you, you.depth);
1955 #endif
1956 
1957     // Save position for hatches to place a marker on the destination level.
1958     coord_def dest_pos = you.pos();
1959 
1960     _generic_level_reset();
1961 
1962     // We clear twice - on save and on load.
1963     // Once would be enough...
1964     if (make_changes)
1965         delete_all_clouds();
1966 
1967     // This block is to grab followers and save the old level to disk.
1968     if (load_mode == LOAD_ENTER_LEVEL)
1969     {
1970         dprf("stair_taken = %s", dungeon_feature_name(stair_taken));
1971         // Not the case normally, but can happen during recovery of damaged
1972         // games.
1973         if (old_level.depth != -1)
1974         {
1975             _grab_followers();
1976 
1977             if (env.level_state & LSTATE_DELETED)
1978                 delete_level(old_level), dprf("<lightmagenta>Deleting level.</lightmagenta>");
1979             else
1980                 save_level(old_level);
1981         }
1982 
1983         // The player is now between levels.
1984         you.position.reset();
1985 
1986         update_companions();
1987     }
1988 
1989 #ifdef USE_TILE
1990     if (load_mode != LOAD_VISITOR)
1991     {
1992         tiles.clear_minimap();
1993         crawl_view_buffer empty_vbuf;
1994         tiles.load_dungeon(empty_vbuf, crawl_view.vgrdc);
1995     }
1996 #endif
1997 
1998     if (load_mode != LOAD_VISITOR
1999         && you.chapter == CHAPTER_POCKET_ABYSS
2000         && player_in_branch(BRANCH_DUNGEON))
2001     {
2002         // If we're leaving the Abyss for the first time as a Chaos
2003         // Knight of Lugonu (who start out there), enable normal monster
2004         // generation.
2005         you.chapter = CHAPTER_ORB_HUNTING;
2006     }
2007 
2008     // GENERATE new level(s) when the file can't be opened:
2009     if (pregen_dungeon(level_id::current()))
2010     {
2011         // sanity check: did the pregenerator leave us on the requested level? If
2012         // this fails via a bug, and this ASSERT isn't here, something incorrect
2013         // will get saved under the chunk for the current level (typically the
2014         // last level in the pregen sequence, which is zig 27).
2015         ASSERT(you.on_current_level);
2016     }
2017     else
2018     {
2019         if (!you.save->has_chunk(level_name))
2020         {
2021             // The builder has failed somewhere along the way, and couldn't get
2022             // to the stopping point. The most likely (only?) cause is that
2023             // there were too many vetoes, which can occasionally happen in
2024             // Depths. To deal with this we force save and crash.
2025             //
2026             // Basically this will ensure that the rng state after the
2027             // attempt is saved, making resuming likely to be possible. Setting
2028             // `you.on_current_level` means that the save has the player on a
2029             // non-generated level. Reloading a save in this state triggers
2030             // the levelgen sequence needed to put them there.
2031 
2032             // ensure these props can't be saved, otherwise the save is likely
2033             // to become unloadable
2034             if (you.props.exists("force_map")
2035                 || you.props.exists("force_minivault"))
2036             {
2037                 // TODO: is there a good way of doing this without the crash?
2038                 mprf(MSGCH_ERROR, "&P with '%s' failed; clearing force props and trying with random generation next.",
2039                     you.props.exists("force_map")
2040                     ? you.props["force_map"].get_string().c_str()
2041                     : you.props["force_minivault"].get_string().c_str());
2042                 // without a flush this mprf doesn't get saved
2043                 flush_prev_message();
2044                 you.props.erase("force_minivault");
2045                 you.props.erase("force_map");
2046             }
2047 
2048             if (crawl_state.need_save)
2049             {
2050                 you.on_current_level = true;
2051                 save_game(false);
2052             }
2053 
2054             die("Builder failure while generating '%s'!\nLast builder error: '%s'",
2055                 level_id::current().describe().c_str(),
2056                 crawl_state.last_builder_error.c_str());
2057         }
2058 
2059         dprf("Loading old level '%s'.", level_name.c_str());
2060         _restore_tagged_chunk(you.save, level_name, TAG_LEVEL, "Level file is invalid.");
2061         if (load_mode != LOAD_VISITOR)
2062             you.on_current_level = true;
2063         _redraw_all(); // TODO why is there a redraw call here?
2064     }
2065 
2066     const bool just_created_level = !you.level_visited(level_id::current());
2067 
2068     // Clear map knowledge stair emphasis.
2069     show_update_emphasis();
2070 
2071     // Shouldn't happen, but this is too unimportant to assert.
2072     deleteAll(env.final_effects);
2073 
2074     los_changed();
2075 
2076     if (load_mode != LOAD_VISITOR)
2077         you.set_level_visited(level_id::current());
2078 
2079     // Markers must be activated early, since they may rely on
2080     // events issued later, e.g. DET_ENTERING_LEVEL or
2081     // the DET_TURN_ELAPSED from update_level.
2082     if (make_changes || load_mode == LOAD_RESTART_GAME)
2083         env.markers.activate_all();
2084 
2085     if (make_changes && env.elapsed_time && !just_created_level)
2086         update_level(you.elapsed_time - env.elapsed_time);
2087 
2088     // Apply all delayed actions, if any. TODO: logic for marshalling this is
2089     // kind of odd.
2090     // TODO: does this need make_changes?
2091     if (just_created_level)
2092         env.dactions_done = 0;
2093 
2094     // Here's the second cloud clearing, on load (see above).
2095     if (make_changes)
2096     {
2097         // this includes various things that are irrelevant for new levels, but
2098         // also some things that aren't, such as bribe branch.
2099         catchup_dactions();
2100 
2101         delete_all_clouds();
2102 
2103         _place_player(stair_taken, return_pos, dest_pos, hatch_name);
2104     }
2105 
2106     crawl_view.set_player_at(you.pos(), load_mode != LOAD_VISITOR);
2107 
2108     // Actually "move" the followers if applicable.
2109     if (load_mode == LOAD_ENTER_LEVEL)
2110         place_followers();
2111 
2112     // Load monsters in transit.
2113     if (load_mode == LOAD_ENTER_LEVEL)
2114         place_transiting_monsters();
2115 
2116     if (just_created_level && make_changes)
2117         replace_boris();
2118 
2119     if (make_changes)
2120     {
2121         // Tell stash-tracker and travel that we've changed levels.
2122         trackers_init_new_level();
2123         tile_new_level(just_created_level);
2124     }
2125     else if (load_mode == LOAD_RESTART_GAME)
2126     {
2127         _rescue_player_from_wall();
2128         // Travel needs initialize some things on reload, too.
2129         travel_init_load_level();
2130     }
2131 
2132     _redraw_all();
2133 
2134     if (load_mode != LOAD_VISITOR)
2135         dungeon_events.fire_event(DET_ENTERING_LEVEL);
2136 
2137     // Things to update for player entering level
2138     if (load_mode == LOAD_ENTER_LEVEL)
2139     {
2140         // new levels have less wary monsters, and we don't
2141         // want them to attack players quite as soon:
2142         you.time_taken *= (just_created_level ? 1 : 2);
2143 
2144         you.time_taken = div_rand_round(you.time_taken * 3, 4);
2145 
2146         dprf("arrival time: %d", you.time_taken);
2147 
2148         if (just_created_level)
2149             run_map_epilogues();
2150     }
2151 
2152     // Save the created/updated level out to disk:
2153     if (make_changes)
2154         save_level(level_id::current());
2155 
2156     setup_environment_effects();
2157 
2158     setup_vault_mon_list();
2159 
2160     // Inform user of level's annotation.
2161     if (load_mode != LOAD_VISITOR
2162         && !get_level_annotation().empty()
2163         && !crawl_state.level_annotation_shown)
2164     {
2165         mprf(MSGCH_PLAIN, YELLOW, "Level annotation: %s",
2166              get_level_annotation().c_str());
2167     }
2168 
2169     if (load_mode != LOAD_VISITOR)
2170         crawl_state.level_annotation_shown = false;
2171 
2172     if (make_changes)
2173     {
2174         // Update PlaceInfo entries
2175         PlaceInfo& curr_PlaceInfo = you.get_place_info();
2176         PlaceInfo  delta;
2177 
2178         if (load_mode == LOAD_START_GAME
2179             || (load_mode == LOAD_ENTER_LEVEL
2180                 && old_level.branch != you.where_are_you
2181                 && !popped))
2182         {
2183             delta.num_visits++;
2184         }
2185 
2186         if (just_created_level)
2187             delta.levels_seen++;
2188 
2189         you.global_info += delta;
2190 #ifdef DEBUG_LEVEL_LOAD
2191         mprf(MSGCH_DIAGNOSTICS,
2192              "global_info:: num_visits: %d, levels_seen: %d",
2193              you.global_info.num_visits, you.global_info.levels_seen);
2194 #endif
2195         you.global_info.assert_validity();
2196 
2197         curr_PlaceInfo += delta;
2198 #ifdef DEBUG_LEVEL_LOAD
2199         mprf(MSGCH_DIAGNOSTICS,
2200              "curr_PlaceInfo:: num_visits: %d, levels_seen: %d",
2201              curr_PlaceInfo.num_visits, curr_PlaceInfo.levels_seen);
2202 #endif
2203 #if TAG_MAJOR_VERSION == 34
2204         // this fixup is for a bug where turns_on_level==0 was used to set
2205         // just_created_level, and there were some obscure ways to have 0
2206         // turns on a level that you had entered previously. It only applies
2207         // to a narrow version range (basically 0.23.0) but there's no way to
2208         // do a sensible minor version check here and the fixup can't happen
2209         // on load.
2210         if (is_connected_branch(curr_PlaceInfo.branch)
2211             && brdepth[curr_PlaceInfo.branch] > 0
2212             && static_cast<int>(curr_PlaceInfo.levels_seen)
2213                                         > brdepth[curr_PlaceInfo.branch])
2214         {
2215             mprf(MSGCH_ERROR,
2216                 "Fixing up corrupted PlaceInfo for %s (levels_seen is %d)",
2217                 branches[curr_PlaceInfo.branch].shortname,
2218                 curr_PlaceInfo.levels_seen);
2219             curr_PlaceInfo.levels_seen = brdepth[curr_PlaceInfo.branch];
2220         }
2221 #endif
2222         curr_PlaceInfo.assert_validity();
2223     }
2224 
2225     if (just_created_level && make_changes)
2226     {
2227         you.attribute[ATTR_ABYSS_ENTOURAGE] = 0;
2228         gozag_detect_level_gold(true);
2229     }
2230 
2231 
2232     if (load_mode != LOAD_VISITOR)
2233     {
2234         dungeon_events.fire_event(
2235                         dgn_event(DET_ENTERED_LEVEL, coord_def(), you.time_taken,
2236                                   load_mode == LOAD_RESTART_GAME));
2237     }
2238 
2239     if (load_mode == LOAD_ENTER_LEVEL)
2240     {
2241         // 50% chance of repelling the stair you just came through.
2242         if (you.duration[DUR_REPEL_STAIRS_MOVE]
2243             || you.duration[DUR_REPEL_STAIRS_CLIMB])
2244         {
2245             dungeon_feature_type feat = env.grid(you.pos());
2246             if (feat != DNGN_ENTER_SHOP
2247                 && feat_stair_direction(feat) != CMD_NO_CMD
2248                 && feat_stair_direction(stair_taken) != CMD_NO_CMD)
2249             {
2250                 string stair_str = feature_description_at(you.pos(), false,
2251                                                           DESC_THE);
2252                 string verb = stair_climb_verb(feat);
2253 
2254                 if (coinflip()
2255                     && slide_feature_over(you.pos()))
2256                 {
2257                     mprf("%s slides away from you right after you %s it!",
2258                          stair_str.c_str(), verb.c_str());
2259                 }
2260 
2261                 if (coinflip())
2262                 {
2263                     // Stairs stop fleeing from you now you actually caught one.
2264                     mprf("%s settles down.", stair_str.c_str());
2265                     you.duration[DUR_REPEL_STAIRS_MOVE]  = 0;
2266                     you.duration[DUR_REPEL_STAIRS_CLIMB] = 0;
2267                 }
2268             }
2269         }
2270 
2271         ash_detect_portals(is_map_persistent());
2272 
2273         if (just_created_level)
2274             xom_new_level_noise_or_stealth();
2275     }
2276 
2277     if (just_created_level && (load_mode == LOAD_ENTER_LEVEL
2278                                || load_mode == LOAD_START_GAME))
2279     {
2280         decr_zot_clock();
2281     }
2282 
2283     // Initialize halos, etc.
2284     invalidate_agrid(true);
2285 
2286     // Maybe make a note if we reached a new level.
2287     // Don't do so if we are just moving around inside Pan, though.
2288     if (just_created_level && make_changes
2289         && stair_taken != DNGN_TRANSIT_PANDEMONIUM)
2290     {
2291         take_note(Note(NOTE_DUNGEON_LEVEL_CHANGE));
2292     }
2293 
2294     // If the player entered the level from a different location than they last
2295     // exited it, have monsters lose track of where they are
2296     if (make_changes && you.position != env.old_player_pos)
2297        shake_off_monsters(you.as_player());
2298 
2299 #if TAG_MAJOR_VERSION == 34
2300     if (make_changes && you.props.exists("zig-fixup")
2301         && you.where_are_you == BRANCH_TOMB
2302         && you.depth == brdepth[BRANCH_TOMB])
2303     {
2304         if (!just_created_level)
2305         {
2306             int obj = items(false, OBJ_MISCELLANY, MISC_ZIGGURAT, 0);
2307             ASSERT(obj != NON_ITEM);
2308             bool success = move_item_to_grid(&obj, you.pos(), true);
2309             ASSERT(success);
2310         }
2311         you.props.erase("zig-fixup");
2312     }
2313 #endif
2314 
2315     return just_created_level;
2316 }
2317 
save_level(const level_id & lid)2318 void save_level(const level_id& lid)
2319 {
2320     if (you.level_visited(lid))
2321         travel_cache.get_level_info(lid).update();
2322 
2323     // Nail all items to the ground.
2324     fix_item_coordinates();
2325 
2326     _write_tagged_chunk(lid.describe(), TAG_LEVEL);
2327 }
2328 
2329 #if TAG_MAJOR_VERSION == 34
2330 # define CHUNK(short, long) short
2331 #else
2332 # define CHUNK(short, long) long
2333 #endif
2334 
2335 #define SAVEFILE(short, long, savefn)           \
2336     do                                          \
2337     {                                           \
2338         writer w(you.save, CHUNK(short, long)); \
2339         savefn(w);                              \
2340     } while (false)
2341 
2342 // Stack allocated string's go in separate function, so Valgrind doesn't
2343 // complain.
_save_game_base()2344 static void _save_game_base()
2345 {
2346     /* Stashes */
2347     SAVEFILE("st", "stashes", StashTrack.save);
2348 
2349     /* lua */
2350     SAVEFILE("lua", "lua", clua.save); // what goes in here?
2351 
2352     /* kills */
2353     SAVEFILE("kil", "kills", you.kills.save);
2354 
2355     /* travel cache */
2356     SAVEFILE("tc", "travel_cache", travel_cache.save);
2357 
2358     /* notes */
2359     SAVEFILE("nts", "notes", save_notes);
2360 
2361     /* tutorial/hints mode */
2362     if (crawl_state.game_is_hints_tutorial())
2363         SAVEFILE("tut", "tutorial", save_hints);
2364 
2365     /* messages */
2366     SAVEFILE("msg", "messages", save_messages);
2367 
2368     /* tile dolls (empty for ASCII)*/
2369 #ifdef USE_TILE
2370     // Save the current equipment into a file.
2371     SAVEFILE("tdl", "tiles_doll", save_doll_file);
2372 #endif
2373 
2374     _write_tagged_chunk("you", TAG_YOU);
2375     _write_tagged_chunk("chr", TAG_CHR);
2376 }
2377 
2378 // Stack allocated string's go in separate function, so Valgrind doesn't
2379 // complain.
_save_game_exit()2380 static void _save_game_exit()
2381 {
2382     clua.save_persist();
2383 
2384     // Prompt for saving macros.
2385     if (crawl_state.unsaved_macros)
2386         macro_save();
2387 
2388     // Must be exiting -- save level & goodbye!
2389     if (!you.entering_level)
2390         save_level(level_id::current());
2391 
2392     clrscr();
2393 
2394 #ifdef DGL_WHEREIS
2395     whereis_record("saved");
2396 #endif
2397 #ifdef USE_TILE_WEB
2398     tiles.send_exit_reason("saved");
2399 #endif
2400 
2401     delete you.save;
2402     you.save = 0;
2403 }
2404 
save_game(bool leave_game,const char * farewellmsg)2405 void save_game(bool leave_game, const char *farewellmsg)
2406 {
2407     unwind_bool saving_game(crawl_state.saving_game, true);
2408     // Should you.no_save disable more here? Currently it entails an empty
2409     // package, and persists won't save, but there's a bunch of other stuff
2410     // that can.
2411     ASSERT(you.on_current_level || Options.no_save);
2412 
2413 
2414     if (leave_game && Options.dump_on_save)
2415     {
2416         if (!dump_char(you.your_name, true))
2417         {
2418             mpr("Char dump unsuccessful! Sorry about that.");
2419             if (!crawl_state.seen_hups)
2420                 more();
2421         }
2422 #ifdef USE_TILE_WEB
2423         else
2424             tiles.send_dump_info("save", you.your_name);
2425 #endif
2426     }
2427 
2428     // Stack allocated string's go in separate function,
2429     // so Valgrind doesn't complain.
2430     _save_game_base();
2431 
2432     // If just save, early out.
2433     if (!leave_game)
2434     {
2435         if (!crawl_state.disables[DIS_SAVE_CHECKPOINTS])
2436             you.save->commit();
2437         return;
2438     }
2439 
2440     // Stack allocated string's go in separate function,
2441     // so Valgrind doesn't complain.
2442     _save_game_exit();
2443 
2444     game_ended(game_exit::save, farewellmsg ? farewellmsg
2445                                 : "See you soon, " + you.your_name + "!");
2446 }
2447 
2448 // Saves the game without exiting.
save_game_state()2449 void save_game_state()
2450 {
2451     save_game(false);
2452     if (crawl_state.seen_hups)
2453         save_game(true);
2454 }
2455 
_bones_save_individual_levels(bool store)2456 static bool _bones_save_individual_levels(bool store)
2457 {
2458     // Only use level-numbered bones files for places where players die a lot.
2459     // For the permastore, go even coarser (just D and Lair use level numbers).
2460     // n.b. some branches here may not currently generate ghosts.
2461     // TODO: further adjustments? Make Zot coarser?
2462     return store ? player_in_branch(BRANCH_DUNGEON) ||
2463                    player_in_branch(BRANCH_LAIR)
2464                  : !(player_in_branch(BRANCH_ZIGGURAT) ||
2465                      player_in_branch(BRANCH_CRYPT) ||
2466                      player_in_branch(BRANCH_TOMB) ||
2467                      player_in_branch(BRANCH_ABYSS) ||
2468                      player_in_branch(BRANCH_SLIME));
2469 }
2470 
_make_ghost_filename(bool store=false)2471 static string _make_ghost_filename(bool store=false)
2472 {
2473     const bool with_number = _bones_save_individual_levels(store);
2474     // Players die so rarely in hell in practice that it doesn't even make
2475     // sense to have per-hell bones. (Maybe vestibule should be separate?)
2476     const string level_desc = player_in_hell(true) ? "Hells" :
2477         replace_all(level_id::current().describe(false, with_number), ":", "-");
2478     return string("bones.") + (store ? "store." : "") + level_desc;
2479 }
2480 
_bones_permastore_file()2481 static string _bones_permastore_file()
2482 {
2483     string filename = _make_ghost_filename(true);
2484     string full_path = _get_bonefile_directory() + filename;
2485     if (file_exists(full_path))
2486         return full_path;
2487 
2488     string dist_full_path = datafile_path(
2489             string("dist_bones") + FILE_SEPARATOR + filename, false, false);
2490     if (dist_full_path.empty())
2491         return dist_full_path;
2492 
2493     // no matching permastore is in the player's bones file, but one exists in
2494     // the crawl distribution. Install it.
2495 
2496     FILE *src = fopen(dist_full_path.c_str(), "rb");
2497     if (!src)
2498     {
2499         mprf(MSGCH_ERROR, "Bones file exists but can't be opened: %s",
2500             dist_full_path.c_str());
2501         return "";
2502     }
2503     FILE *target = lk_open("wb", full_path);
2504     if (!target)
2505     {
2506         mprf(MSGCH_ERROR, "Unable to open bones file %s for writing",
2507             full_path.c_str());
2508         fclose(src);
2509         return "";
2510     }
2511 
2512     _ghost_dprf("Copying %s to %s", dist_full_path.c_str(), full_path.c_str());
2513 
2514     char buf[BUFSIZ];
2515 
2516     size_t size;
2517     while ((size = fread(buf, sizeof(char), BUFSIZ, src)) > 0)
2518         fwrite(buf, sizeof(char), size, target);
2519 
2520     lk_close(target);
2521 
2522     if (!feof(src))
2523     {
2524         mprf(MSGCH_ERROR, "Error installing bones file to %s",
2525                                                     full_path.c_str());
2526         if (unlink(full_path.c_str()) != 0)
2527         {
2528             mprf(MSGCH_ERROR,
2529                 "Failed to unlink probably corrupt bones file: %s",
2530                 full_path.c_str());
2531         }
2532         fclose(src);
2533         return "";
2534     }
2535     fclose(src);
2536     return full_path;
2537 }
2538 
2539 // Bones files
2540 //
2541 // There are two kinds of bones files: temporary bones files and the
2542 // permastore. Temporary bones files are ephemeral: ghosts will be reused only
2543 // if they are on the floor where the player dies. The permastore is a more
2544 // permanent stock of ghosts (per level) to use as a backup in case the
2545 // temporary bones files are depleted.
2546 
2547 /**
2548  * Lists all bonefiles for the current level.
2549  *
2550  * @return A vector containing absolute paths to 0+ bonefiles.
2551  */
_list_bones()2552 static vector<string> _list_bones()
2553 {
2554     string bonefile_dir = _get_bonefile_directory();
2555     string base_filename = _make_ghost_filename();
2556     string underscored_filename = base_filename + "_";
2557 
2558     vector<string> filenames = get_dir_files_sorted(bonefile_dir);
2559     vector<string> bonefiles;
2560     for (const auto &filename : filenames)
2561         if (starts_with(filename, underscored_filename)
2562                                             && !ends_with(filename, ".backup"))
2563         {
2564             bonefiles.push_back(bonefile_dir + filename);
2565             _ghost_dprf("bonesfile %s", (bonefile_dir + filename).c_str());
2566         }
2567 
2568     string old_bonefile = _get_old_bonefile_directory() + base_filename;
2569     if (access(old_bonefile.c_str(), F_OK) == 0)
2570     {
2571         _ghost_dprf("Found old bonefile %s", old_bonefile.c_str());
2572         bonefiles.push_back(old_bonefile);
2573     }
2574 
2575     return bonefiles;
2576 }
2577 
2578 /**
2579  * Attempts to find a file containing ghost(s) appropriate for the player.
2580  *
2581  * @return The filename of an appropriate bones file; may be "".
2582  */
_find_ghost_file()2583 static string _find_ghost_file()
2584 {
2585     vector<string> bonefiles = _list_bones();
2586     if (bonefiles.empty())
2587         return "";
2588     return bonefiles[random2(bonefiles.size())];
2589 }
2590 
_old_bones_filename(string ghost_filename,const save_version & v)2591 static string _old_bones_filename(string ghost_filename, const save_version &v)
2592 {
2593     // TODO: a way of looking for any backup with a version earlier than v
2594     if (ends_with(ghost_filename, ".backup"))
2595         return ghost_filename; // already an old bones file
2596 
2597     string new_filename = make_stringf("%s-v%d.%d.backup", ghost_filename.c_str(),
2598                                         v.major, v.minor);
2599     return new_filename;
2600 }
2601 
_backup_bones_for_upgrade(string ghost_filename,save_version & v)2602 static bool _backup_bones_for_upgrade(string ghost_filename, save_version &v)
2603 {
2604     // Copy the bones file to a versioned name, so that non-upgraded saves can
2605     // load it. Copying would be cleaner with c++ ios stuff, but we need to
2606     // interact with the lock system.
2607 
2608     if (ghost_filename.empty())
2609         return false;
2610     if (ends_with(ghost_filename, ".backup"))
2611         return false; // already an old bones file
2612 
2613     string upgrade_filename = _old_bones_filename(ghost_filename, v);
2614     if (file_exists(upgrade_filename))
2615         return false;
2616     _ghost_dprf("Backing up bones file %s to %s before upgrade to %d.%d",
2617                             ghost_filename.c_str(), upgrade_filename.c_str(),
2618                             save_version::current_bones().major,
2619                             save_version::current_bones().minor);
2620 
2621     FILE *backup_src = lk_open("rb", ghost_filename);
2622     if (!backup_src)
2623     {
2624         mprf(MSGCH_ERROR, "Bones file to back up doesn't exist: %s",
2625             ghost_filename.c_str());
2626         return false;
2627     }
2628     FILE *backup_target = lk_open("wb", upgrade_filename);
2629     if (!backup_target)
2630     {
2631         mprf(MSGCH_ERROR, "Unable to open bones backup file %s for writing",
2632             upgrade_filename.c_str());
2633         lk_close(backup_src);
2634         return false;
2635     }
2636 
2637     char buf[BUFSIZ];
2638 
2639     size_t size;
2640     while ((size = fread(buf, sizeof(char), BUFSIZ, backup_src)) > 0)
2641         fwrite(buf, sizeof(char), size, backup_target);
2642 
2643     lk_close(backup_target);
2644 
2645     if (!feof(backup_src))
2646     {
2647         mprf(MSGCH_ERROR, "Error backing up bones file to %s",
2648                                                     upgrade_filename.c_str());
2649         if (unlink(upgrade_filename.c_str()) != 0)
2650         {
2651             mprf(MSGCH_ERROR,
2652                 "Failed to unlink probably corrupt bones file: %s",
2653                 upgrade_filename.c_str());
2654         }
2655         lk_close(backup_src);
2656         return false;
2657     }
2658     lk_close(backup_src);
2659     return true;
2660 }
2661 
read_ghost_header(reader & inf)2662 save_version read_ghost_header(reader &inf)
2663 {
2664     auto version = get_save_version(inf);
2665     if (!version.valid())
2666         return version;
2667 
2668 #if TAG_MAJOR_VERSION == 34
2669     // downgrade bones files saved before the bones sub-versioning system
2670     if (version > save_version::current_bones() && version.is_compatible())
2671     {
2672         _ghost_dprf("Setting bones file version from %d.%d to %d.%d on load",
2673             version.major, version.minor,
2674             save_version::current_bones().major,
2675             save_version::current_bones().minor);
2676         version = save_version::current_bones();
2677     }
2678 #endif
2679 
2680     try
2681     {
2682         // Check for the DCSS ghost signature.
2683         if (unmarshallShort(inf) != GHOST_SIGNATURE)
2684             return save_version(); // version was valid, but this isn't a bones file
2685 
2686         // Discard three more 32-bit words of padding.
2687         inf.read(nullptr, 3*4);
2688     }
2689     catch (short_read_exception &E)
2690     {
2691         mprf(MSGCH_ERROR,
2692              "Ghost file \"%s\" seems to be invalid (short read); deleting it.",
2693              inf.filename().c_str());
2694         return save_version();
2695     }
2696 
2697     return version;
2698 }
2699 
load_bones_file(string ghost_filename,bool backup)2700 vector<ghost_demon> load_bones_file(string ghost_filename, bool backup)
2701 {
2702     vector<ghost_demon> result;
2703 
2704     if (ghost_filename.empty())
2705         return result; // no such ghost.
2706 
2707     reader inf(ghost_filename);
2708     if (!inf.valid())
2709     {
2710         // file doesn't exist
2711         _ghost_dprf("Ghost file '%s' invalid before read.", ghost_filename.c_str());
2712         return result;
2713     }
2714 
2715     inf.set_safe_read(true); // don't die on 0-byte bones
2716     save_version version = read_ghost_header(inf);
2717     if (!_ghost_version_compatible(version))
2718     {
2719         string error = "Incompatible bones file: " + ghost_filename;
2720         throw corrupted_save(error, version);
2721     }
2722     inf.setMinorVersion(version.minor);
2723     if (backup && version < save_version::current_bones())
2724         _backup_bones_for_upgrade(ghost_filename, version);
2725 
2726     try
2727     {
2728         result = tag_read_ghosts(inf);
2729         inf.fail_if_not_eof(ghost_filename);
2730     }
2731     catch (short_read_exception &short_read)
2732     {
2733         string error = "Broken bones file: " + ghost_filename;
2734         throw corrupted_save(error, version);
2735     }
2736     inf.close();
2737 
2738     if (!debug_check_ghosts(result))
2739     {
2740         string error = "Bones file is buggy: " + ghost_filename;
2741         throw corrupted_save(error, version);
2742     }
2743 
2744     return result;
2745 }
2746 
2747 
_load_ghosts_core(string filename,bool backup_on_upgrade)2748 static vector<ghost_demon> _load_ghosts_core(string filename,
2749                                                         bool backup_on_upgrade)
2750 {
2751     vector<ghost_demon> results;
2752     try
2753     {
2754         results = load_bones_file(filename, backup_on_upgrade);
2755     }
2756     catch (corrupted_save &err)
2757     {
2758         // not a corrupted save per se, just from the future. Try to load the
2759         // versioned bones file if it exists.
2760         if (err.version.valid() && err.version.is_future())
2761         {
2762             string old_bones =
2763                         _old_bones_filename(filename, save_version::current());
2764             if (old_bones != filename)
2765             {
2766                 _ghost_dprf("Loading ghost from backup bones file %s",
2767                                                         old_bones.c_str());
2768                 return load_bones_file(old_bones, false);
2769             }
2770             else
2771                 mprf(MSGCH_ERROR, "Mismatch between bones backup "
2772                     "filename '%s' and version %d.%d!", filename.c_str(),
2773                     err.version.major, err.version.minor);
2774             // intentional fallthrough -- unlink the misnamed file
2775         }
2776         else
2777             mprf(MSGCH_ERROR, "%s", err.what());
2778         string report;
2779         // if we get to this point the bones file is unreadable and needs to
2780         // be scrapped
2781         if (unlink(filename.c_str()) != 0)
2782             report = "Failed to unlink bad bones file";
2783         else
2784             report = "Clearing bad bones file";
2785         mprf(MSGCH_ERROR, "%s: %s", report.c_str(), filename.c_str());
2786     }
2787     return results;
2788 
2789 }
2790 
_load_ephemeral_ghosts()2791 static vector<ghost_demon> _load_ephemeral_ghosts()
2792 {
2793     vector<ghost_demon> results;
2794 
2795     string ghost_filename = _find_ghost_file();
2796     if (ghost_filename.empty())
2797     {
2798         _ghost_dprf("%s", "No ephemeral ghost files for this level.");
2799         return results; // no such ghost.
2800     }
2801 
2802     results = _load_ghosts_core(ghost_filename, true);
2803 
2804     if (unlink(ghost_filename.c_str()) != 0)
2805     {
2806         mprf(MSGCH_ERROR, "Failed to unlink bones file: %s",
2807                 ghost_filename.c_str());
2808     }
2809     return results;
2810 }
2811 
_load_permastore_ghosts(bool backup_on_upgrade=false)2812 static vector<ghost_demon> _load_permastore_ghosts(bool backup_on_upgrade=false)
2813 {
2814     return _load_ghosts_core(_bones_permastore_file(), backup_on_upgrade);
2815 }
2816 
2817 /**
2818  * Attempt to fill in a monster based on bones files.
2819  *
2820  * @param mons the monster to fill in
2821  *
2822  * @return whether there was a saved ghost that could be used.
2823  */
define_ghost_from_bones(monster & mons)2824 bool define_ghost_from_bones(monster& mons)
2825 {
2826     rng::generator rng(rng::SYSTEM_SPECIFIC);
2827 
2828     bool used_permastore = false;
2829 
2830     vector<ghost_demon> loaded_ghosts = _load_ephemeral_ghosts();
2831     if (loaded_ghosts.empty())
2832     {
2833         loaded_ghosts = _load_permastore_ghosts();
2834         if (loaded_ghosts.empty())
2835             return false;
2836         used_permastore = true;
2837     }
2838 
2839     int place_i = random2(loaded_ghosts.size());
2840     _ghost_dprf("Loaded ghost file with %u ghost(s), placing %s",
2841          (unsigned int)loaded_ghosts.size(), loaded_ghosts[place_i].name.c_str());
2842 
2843     mons.set_ghost(loaded_ghosts[place_i]);
2844     mons.type = MONS_PLAYER_GHOST;
2845     mons.ghost_init(false);
2846 
2847     if (!mons.alive())
2848         mprf(MSGCH_ERROR, "Placed ghost is not alive.");
2849     else if (mons.type != MONS_PLAYER_GHOST)
2850     {
2851         mprf(MSGCH_ERROR, "Placed ghost is not MONS_PLAYER_GHOST, but %s",
2852              mons.name(DESC_PLAIN, true).c_str());
2853     }
2854 
2855     if (!used_permastore)
2856     {
2857         loaded_ghosts.erase(loaded_ghosts.begin() + place_i);
2858 
2859         if (!loaded_ghosts.empty())
2860             save_ghosts(loaded_ghosts);
2861     }
2862     return true;
2863 }
2864 
2865 /**
2866  * Attempt to load one or more ghosts into the level.
2867  *
2868  * @param max_ghosts        A maximum number of ghosts to creat.
2869  *                          Set to <= 0 to load as many as possible.
2870  * @param creating_level    Whether a level is currently being generated.
2871  * @return                  Whether ghosts were actually generated.
2872  */
load_ghosts(int max_ghosts,bool creating_level)2873 bool load_ghosts(int max_ghosts, bool creating_level)
2874 {
2875     ASSERT(you.transit_stair == DNGN_UNSEEN || creating_level);
2876     ASSERT(!you.entering_level || creating_level);
2877     ASSERT(!creating_level
2878            || (you.entering_level && you.transit_stair != DNGN_UNSEEN));
2879     // Only way to load a ghost without creating a level is via a wizard
2880     // command.
2881     ASSERT(creating_level || (crawl_state.prev_cmd == CMD_WIZARD));
2882 
2883 #ifdef BONES_DIAGNOSTICS
2884     // this is pretty hacky, but arguably cleaner than what it is replacing.
2885     // The effect is to show bones diagnostic messages on wizmode builds during
2886     // level building
2887     unwind_var<command_type> last_cmd(crawl_state.prev_cmd, creating_level ?
2888         CMD_WIZARD : crawl_state.prev_cmd);
2889 #endif
2890 
2891     vector<ghost_demon> loaded_ghosts = _load_ephemeral_ghosts();
2892 
2893     _ghost_dprf("Loaded ghost file with %u ghost(s), will attempt to place %d of them",
2894              (unsigned int)loaded_ghosts.size(), max_ghosts);
2895 
2896     bool ghost_errors = false;
2897 
2898     max_ghosts = max_ghosts <= 0 ? loaded_ghosts.size()
2899                                  : min(max_ghosts, (int) loaded_ghosts.size());
2900     int placed_ghosts = 0;
2901 
2902     // Translate ghost to monster and place.
2903     while (!loaded_ghosts.empty() && placed_ghosts < max_ghosts)
2904     {
2905         monster * const mons = get_free_monster();
2906         if (!mons)
2907             break;
2908 
2909         mons->set_new_monster_id();
2910         mons->set_ghost(loaded_ghosts[0]);
2911         mons->type = MONS_PLAYER_GHOST;
2912         mons->ghost_init();
2913 
2914         loaded_ghosts.erase(loaded_ghosts.begin());
2915         placed_ghosts++;
2916 
2917         if (!mons->alive())
2918         {
2919             _ghost_dprf("Placed ghost is not alive.");
2920             ghost_errors = true;
2921         }
2922         else if (mons->type != MONS_PLAYER_GHOST)
2923         {
2924             _ghost_dprf("Placed ghost is not MONS_PLAYER_GHOST, but %s",
2925                  mons->name(DESC_PLAIN, true).c_str());
2926             ghost_errors = true;
2927         }
2928     }
2929 
2930     if (placed_ghosts < max_ghosts)
2931     {
2932         _ghost_dprf("Unable to place %u ghost(s)", max_ghosts - placed_ghosts);
2933         ghost_errors = true;
2934     }
2935 #ifdef BONES_DIAGNOSTICS
2936     if (ghost_errors)
2937         more();
2938 #endif
2939 
2940     // resave any unused ghosts
2941     if (!loaded_ghosts.empty())
2942         save_ghosts(loaded_ghosts);
2943 
2944     return true;
2945 }
2946 
_type_name_processed(game_type t)2947 static string _type_name_processed(game_type t)
2948 {
2949     string name = game_state::game_type_name_for(t);
2950     return name.size() ? name : "regular";
2951 }
2952 
2953 // returns false if a new game should start instead
_restore_game(const string & filename)2954 static bool _restore_game(const string& filename)
2955 {
2956     if (Options.no_save)
2957         return false;
2958 
2959     // In webtiles, a more before the player is loaded will crash when it tries
2960     // to send enough information to the webtiles client to render the display.
2961     // This is just cosmetic for other build targets.
2962     unwind_bool save_more(crawl_state.show_more_prompt, false);
2963     game_type menu_game_type = crawl_state.type;
2964 
2965     clear_message_store();
2966 
2967     you.save = new package((_get_savefile_directory() + filename).c_str(), true);
2968 
2969     if (!_read_char_chunk(you.save))
2970     {
2971         // Note: if we are here, the save info was properly read, it would
2972         // raise an exception otherwise.
2973         if (yesno(("There is an existing game for name '" + you.your_name +
2974                    "' from an incompatible version of Crawl ("
2975                    + you.prev_save_version + ").\n"
2976                    "Unless you reinstall that version, you can't load it.\n"
2977                    "Do you want to DELETE that game and start a new one?"
2978                   ).c_str(),
2979                   true, 'n'))
2980         {
2981             you.save->unlink();
2982             you.save = 0;
2983             return false;
2984         }
2985         if (Options.remember_name)
2986             crawl_state.default_startup_name = you.your_name; // for main menu
2987         you.save->abort();
2988         delete you.save;
2989         you.save = 0;
2990         game_ended(game_exit::abort,
2991             you.your_name + " is from an incompatible version and can't be loaded.");
2992     }
2993 
2994     if (!crawl_state.bypassed_startup_menu
2995         && menu_game_type != crawl_state.type)
2996     {
2997         if (!yesno(("You already have a "
2998                         + _type_name_processed(crawl_state.type) +
2999                     " game saved under the name '" + you.your_name + "';\n"
3000                     "do you want to load that instead?").c_str(),
3001                    true, 'n'))
3002         {
3003             you.save->abort(); // don't even rewrite the header
3004             delete you.save;
3005             you.save = 0;
3006             game_ended(game_exit::abort,
3007                 "Please use a different name to start a new " +
3008                 _type_name_processed(menu_game_type) + " game, then.");
3009         }
3010     }
3011 
3012     if (Options.remember_name)
3013         crawl_state.default_startup_name = you.your_name; // for main menu
3014 
3015     if (numcmp(you.prev_save_version.c_str(), Version::Long, 2) == -1
3016         && version_is_stable(you.prev_save_version.c_str()))
3017     {
3018         if (!yesno(("This game comes from a previous release of Crawl (" +
3019                     you.prev_save_version + ").\n\nIf you load it now,"
3020                     " you won't be able to go back. Continue?").c_str(),
3021                     true, 'n'))
3022         {
3023             you.save->abort(); // don't even rewrite the header
3024             delete you.save;
3025             you.save = 0;
3026             game_ended(game_exit::abort, "Please use version " +
3027                 you.prev_save_version + " to load " + you.your_name + " then.");
3028         }
3029     }
3030 
3031     you.on_current_level = false; // we aren't on the current level until
3032                                   // everything is fully loaded
3033     _restore_tagged_chunk(you.save, "you", TAG_YOU, "Save data is invalid.");
3034 
3035     _convert_obsolete_species();
3036 
3037     const int minorVersion = crawl_state.minor_version;
3038 
3039     if (you.save->has_chunk(CHUNK("st", "stashes")))
3040     {
3041         reader inf(you.save, CHUNK("st", "stashes"), minorVersion);
3042         StashTrack.load(inf);
3043     }
3044 
3045 #ifdef CLUA_BINDINGS
3046     if (you.save->has_chunk("lua"))
3047     {
3048         vector<char> buf;
3049         chunk_reader inf(you.save, "lua");
3050         inf.read_all(buf);
3051         buf.push_back(0);
3052         clua.execstring(&buf[0]);
3053     }
3054 #endif
3055 
3056     if (you.save->has_chunk(CHUNK("kil", "kills")))
3057     {
3058         reader inf(you.save, CHUNK("kil", "kills"),minorVersion);
3059         you.kills.load(inf);
3060     }
3061 
3062     if (you.save->has_chunk(CHUNK("tc", "travel_cache")))
3063     {
3064         reader inf(you.save, CHUNK("tc", "travel_cache"), minorVersion);
3065         travel_cache.load(inf, minorVersion);
3066     }
3067 
3068     if (you.save->has_chunk(CHUNK("nts", "notes")))
3069     {
3070         reader inf(you.save, CHUNK("nts", "notes"), minorVersion);
3071         load_notes(inf);
3072     }
3073 
3074     /* hints mode */
3075     if (you.save->has_chunk(CHUNK("tut", "tutorial")))
3076     {
3077         reader inf(you.save, CHUNK("tut", "tutorial"), minorVersion);
3078         load_hints(inf);
3079     }
3080 
3081     /* messages */
3082     if (you.save->has_chunk(CHUNK("msg", "messages")))
3083     {
3084         reader inf(you.save, CHUNK("msg", "messages"), minorVersion);
3085         load_messages(inf);
3086     }
3087 
3088     // Handle somebody SIGHUP'ing out of the skill menu with every skill
3089     // disabled. Doing this here rather in tags code because it can trigger
3090     // UI, which may not be safe if everything isn't fully loaded.
3091     check_selected_skills();
3092 
3093     return true;
3094 }
3095 
3096 // returns false if a new game should start instead
restore_game(const string & filename)3097 bool restore_game(const string& filename)
3098 {
3099     try
3100     {
3101         return _restore_game(filename);
3102     }
3103     catch (corrupted_save &err)
3104     {
3105         if (yesno(make_stringf(
3106                    "There exists a save by that name but it appears to be invalid.\n"
3107                    "Do you want to delete it?\n"
3108                    "Error: %s", err.what()).c_str(), // TODO linebreak error
3109                   true, 'n'))
3110         {
3111             if (you.save)
3112                 you.save->unlink();
3113             you.save = 0;
3114             return false;
3115         }
3116         // Shouldn't crash probably...
3117         fail("Aborting; you may try to recover it somehow.");
3118     }
3119 }
3120 
_load_level(const level_id & level)3121 static void _load_level(const level_id &level)
3122 {
3123     // Load the given level.
3124     you.where_are_you = level.branch;
3125     you.depth =         level.depth;
3126 
3127     load_level(DNGN_STONE_STAIRS_DOWN_I, LOAD_VISITOR, level_id());
3128 }
3129 
3130 // Given a level returns true if the level has been created already
3131 // in this game. Warning: after a game has ended, there is a phase where the
3132 // save has been deleted and this check isn't usable, and this is when a moruge
3133 // is generated.
is_existing_level(const level_id & level)3134 bool is_existing_level(const level_id &level)
3135 {
3136     return you.save && you.save->has_chunk(level.describe());
3137 }
3138 
delete_level(const level_id & level)3139 void delete_level(const level_id &level)
3140 {
3141     travel_cache.erase_level_info(level);
3142     StashTrack.remove_level(level);
3143     shopping_list.del_things_from(level);
3144 
3145     clear_level_exclusion_annotation(level);
3146     clear_level_annotations(level);
3147 
3148     if (you.save)
3149         you.save->delete_chunk(level.describe());
3150 
3151     auto &visited = you.props[VISITED_LEVELS_KEY].get_table();
3152     visited.erase(level.describe());
3153 
3154     if (level.branch == BRANCH_ABYSS)
3155     {
3156         save_abyss_uniques();
3157         destroy_abyss();
3158     }
3159     _do_lost_monsters();
3160     _do_lost_items();
3161 }
3162 
3163 // This class provides a way to walk the dungeon with a bit more flexibility
3164 // than you used to get with apply_to_all_dungeons.
level_excursion()3165 level_excursion::level_excursion()
3166     : original(level_id::current()), ever_changed_levels(false)
3167 {
3168 }
3169 
go_to(const level_id & next)3170 void level_excursion::go_to(const level_id& next)
3171 {
3172     // This ASSERT is here because level excursions are often triggered as
3173     // side effects, e.g. in shopping list code, and we really don't want this
3174     // happening during normal levelgen (weird interactions with seeding,
3175     // potential crashes if items or monsters are incomplete, etc). However,
3176     // the abyss purposefully does level excursions in order to pick up
3177     // features from other levels and place them in the abyss: this is
3178     // basically safe to do, and seeding isn't a concern.
3179     ASSERT(!crawl_state.generating_level || original.branch == BRANCH_ABYSS);
3180 
3181     if (level_id::current() != next)
3182     {
3183         if (!you.level_visited(level_id::current()))
3184             travel_cache.erase_level_info(level_id::current());
3185 
3186         ever_changed_levels = true;
3187 
3188         save_level(level_id::current());
3189         _load_level(next);
3190 
3191         if (you.level_visited(next))
3192         {
3193             LevelInfo &li = travel_cache.get_level_info(next);
3194             li.set_level_excludes();
3195         }
3196         // TODO: this won't clear excludes on an excursion to an unvisited
3197         // level. Does this matter? Not right now, this case is only used for
3198         // abyss procgen.
3199     }
3200 
3201     you.on_current_level = (level_id::current() == original);
3202 }
3203 
~level_excursion()3204 level_excursion::~level_excursion()
3205 {
3206     // Go back to original level and reactivate markers if we ever
3207     // left the level.
3208     if (ever_changed_levels)
3209     {
3210         // This may be a no-op if the level-excursion subsequently
3211         // returned to the original level. However, at this point
3212         // markers will still not be activated.
3213         go_to(original);
3214 
3215         // Quietly reactivate markers.
3216         env.markers.activate_all(false);
3217     }
3218 }
3219 
get_save_version(reader & file)3220 save_version get_save_version(reader &file)
3221 {
3222     int major, minor;
3223     try
3224     {
3225         major = unmarshallUByte(file);
3226         minor = unmarshallUByte(file);
3227         if (minor == UINT8_MAX)
3228             minor = unmarshallInt(file);
3229     }
3230     catch (short_read_exception& E)
3231     {
3232         // Empty file?
3233         return save_version(-1, -1);
3234     }
3235     return save_version(major, minor);
3236 }
3237 
write_save_version(writer & outf,save_version version)3238 void write_save_version(writer &outf, save_version version)
3239 {
3240     marshallUByte(outf, version.major);
3241     if (version.minor < UINT8_MAX)
3242         marshallUByte(outf, version.minor);
3243     else
3244     {
3245         marshallUByte(outf, UINT8_MAX);
3246         marshallInt(outf, version.minor);
3247     }
3248 }
3249 
_convert_obsolete_species()3250 static bool _convert_obsolete_species()
3251 {
3252     // At this point the character has been loaded but not resaved, but the grid, lua, stashes, etc have not been.
3253 #if TAG_MAJOR_VERSION == 34
3254     if (you.species == SP_LAVA_ORC)
3255     {
3256         if (!yesno(
3257             "This Lava Orc save game cannot be loaded as-is. If you load it now,\n"
3258             "your character will be converted to a Hill Orc. Continue?",
3259                        false, 'N'))
3260         {
3261             you.save->abort(); // don't even rewrite the header
3262             delete you.save;
3263             you.save = 0;
3264             game_ended(game_exit::abort,
3265                 "Please load the save in an earlier version "
3266                 "if you want to keep it as a Lava Orc.");
3267         }
3268         change_species_to(SP_HILL_ORC);
3269         // No need for conservation
3270         you.innate_mutation[MUT_CONSERVE_SCROLLS]
3271                                 = you.mutation[MUT_CONSERVE_SCROLLS] = 0;
3272         // This is not an elegant way to deal with lava, but at this point the
3273         // level isn't loaded so we can't check the grid features. In
3274         // addition, even if the player isn't over lava, they might still get
3275         // trapped.
3276         fly_player(100);
3277         return true;
3278     }
3279 #endif
3280     return false;
3281 }
3282 
_read_char_chunk(package * save)3283 static bool _read_char_chunk(package *save)
3284 {
3285     reader inf(save, "chr");
3286 
3287     try
3288     {
3289         const auto version = get_save_version(inf);
3290         const auto major = version.major, minor = version.minor;
3291         uint8_t format;
3292 
3293         unsigned int len = unmarshallInt(inf);
3294         if (len > 1024) // something is fishy
3295             fail("Save file corrupted (info > 1KB)");
3296         vector<unsigned char> buf;
3297         buf.resize(len);
3298         inf.read(&buf[0], len);
3299         inf.fail_if_not_eof("chr");
3300         reader th(buf);
3301 
3302         // 0.8 trunks (30.0 .. 32.12) were format 0 but without the marker.
3303         if (major > 32 || major == 32 && minor >= 13)
3304             th.read(&format, 1);
3305         else
3306             format = 0;
3307 
3308         if (format > TAG_CHR_FORMAT)
3309             fail("Incompatible character data");
3310 
3311         tag_read_char(th, format, major, minor);
3312 
3313         // Check if we read everything only on the exact same version,
3314         // but that's the common case.
3315         if (major == TAG_MAJOR_VERSION && minor == TAG_MINOR_VERSION)
3316             inf.fail_if_not_eof("chr");
3317 
3318 #if TAG_MAJOR_VERSION == 34
3319         if (major == 33 && minor == TAG_MINOR_0_11)
3320             return true;
3321 #endif
3322         return major == TAG_MAJOR_VERSION && minor <= TAG_MINOR_VERSION;
3323     }
3324     catch (short_read_exception &E)
3325     {
3326         fail("Save file corrupted");
3327     };
3328 }
3329 
_tagged_chunk_version_compatible(reader & inf,string * reason)3330 static bool _tagged_chunk_version_compatible(reader &inf, string* reason)
3331 {
3332     ASSERT(reason);
3333 
3334     const save_version version = get_save_version(inf);
3335 
3336     if (!version.valid())
3337     {
3338         *reason = make_stringf("File is corrupt (found version %d,%d).",
3339                                 version.major, version.minor);
3340         return false;
3341     }
3342 
3343     if (!version.is_compatible())
3344     {
3345         if (version.is_ancient())
3346         {
3347             const auto min_supported = save_version::minimum_supported();
3348             *reason = make_stringf("This save is from an older version.\n"
3349                     "\n"
3350                     CRAWL " %s is not compatible with save files this old. You can:\n"
3351                     " • continue your game with an older version of " CRAWL "\n"
3352                     " • delete it and start a new game\n"
3353                     "\n"
3354                     "This save's version: (%d.%d) (must be >= %d.%d)",
3355                     Version::Short,
3356                     version.major, version.minor,
3357                     min_supported.major, min_supported.minor);
3358         }
3359         else if (version.is_future())
3360         {
3361             const auto current = save_version::current();
3362             *reason = make_stringf("This save is from a newer version.\n"
3363                     "\n"
3364                     CRAWL " cannot load saves from newer versions. You can:\n"
3365                     " • continue your game with a newer version of " CRAWL "\n"
3366                     " • delete it and start a new game\n"
3367                     "\n"
3368                     "This save's version: (%d.%d) (must be <= %d.%d)",
3369                     version.major, version.minor,
3370                     current.major, current.minor);
3371         }
3372         return false;
3373     }
3374 
3375     inf.setMinorVersion(version.minor);
3376     return true;
3377 }
3378 
_restore_tagged_chunk(package * save,const string & name,tag_type tag,const char * complaint)3379 static bool _restore_tagged_chunk(package *save, const string &name,
3380                                   tag_type tag, const char* complaint)
3381 {
3382     reader inf(save, name);
3383     string reason;
3384     if (!_tagged_chunk_version_compatible(inf, &reason))
3385     {
3386         if (!complaint)
3387         {
3388             dprf("chunk %s: %s", name.c_str(), reason.c_str());
3389             return false;
3390         }
3391         else
3392             end(-1, false, "\n%s %s\n", complaint, reason.c_str());
3393     }
3394 
3395     crawl_state.minor_version = inf.getMinorVersion();
3396     try
3397     {
3398         tag_read(inf, tag);
3399     }
3400     catch (short_read_exception &E)
3401     {
3402         fail("truncated save chunk (%s)", name.c_str());
3403     };
3404 
3405     inf.fail_if_not_eof(name);
3406     return true;
3407 }
3408 
_ghost_version_compatible(const save_version & version)3409 static bool _ghost_version_compatible(const save_version &version)
3410 {
3411     if (!version.valid())
3412         return false;
3413     if (!version.is_compatible())
3414     {
3415         _ghost_dprf("Ghost version mismatch: ghost was %d.%d; current is %d.%d",
3416              version.major, version.minor,
3417              save_version::current().major, save_version::current().minor);
3418         return false;
3419     }
3420     return true;
3421 }
3422 
3423 /**
3424  * Attempt to open a new bones file for saving ghosts.
3425  *
3426  * @param[out] return_gfilename     The name of the file created, if any.
3427  * @return                          A FILE object, or nullptr.
3428  **/
_make_bones_file(string * return_gfilename)3429 static FILE* _make_bones_file(string * return_gfilename)
3430 {
3431     const string bone_dir = _get_bonefile_directory();
3432     const string base_filename = _make_ghost_filename(false);
3433 
3434     for (int i = 0; i < GHOST_LIMIT; i++)
3435     {
3436         const string g_file_name = make_stringf("%s%s_%d", bone_dir.c_str(),
3437                                                 base_filename.c_str(), i);
3438         FILE *ghost_file = lk_open_exclusive(g_file_name);
3439         // need to check file size, so can't open 'wb' - would truncate!
3440 
3441         if (!ghost_file)
3442         {
3443             dprf("Could not open %s", g_file_name.c_str());
3444             continue;
3445         }
3446 
3447         dprf("found %s", g_file_name.c_str());
3448 
3449         *return_gfilename = g_file_name;
3450         return ghost_file;
3451     }
3452 
3453     return nullptr;
3454 }
3455 
3456 #define GHOST_PERMASTORE_SIZE 10
3457 #define GHOST_PERMASTORE_REPLACE_CHANCE 5
3458 
_ghost_permastore_size()3459 static size_t _ghost_permastore_size()
3460 {
3461     if (_bones_save_individual_levels(true))
3462         return GHOST_PERMASTORE_SIZE;
3463     else
3464         return GHOST_PERMASTORE_SIZE * 2;
3465 }
3466 
_update_permastore(const vector<ghost_demon> & ghosts)3467 static vector<ghost_demon> _update_permastore(const vector<ghost_demon> &ghosts)
3468 {
3469     rng::generator rng(rng::SYSTEM_SPECIFIC);
3470     if (ghosts.empty())
3471         return ghosts;
3472 
3473     // this read is not locked...
3474     vector<ghost_demon> permastore = _load_permastore_ghosts();
3475     vector<ghost_demon> leftovers;
3476 
3477     bool rewrite = false;
3478     unsigned int i = 0;
3479     const size_t max_ghosts = _ghost_permastore_size();
3480     while (permastore.size() < max_ghosts && i < ghosts.size())
3481     {
3482         // TODO: heuristics to make this as distinct as possible; maybe
3483         // create a new name?
3484         permastore.push_back(ghosts[i]);
3485 #ifdef DGAMELAUNCH
3486         // randomize name for online play
3487         permastore.back().name = make_name();
3488 #endif
3489         i++;
3490         rewrite = true;
3491     }
3492     if (i > 0)
3493         _ghost_dprf("Permastoring %d ghosts", i);
3494     if (!rewrite && x_chance_in_y(GHOST_PERMASTORE_REPLACE_CHANCE, 100)
3495                                                         && i < ghosts.size())
3496     {
3497         int rewrite_i = random2(permastore.size());
3498         permastore[rewrite_i] = ghosts[i];
3499 #ifdef DGAMELAUNCH
3500         permastore[rewrite_i].name = make_name();
3501 #endif
3502         rewrite = true;
3503     }
3504     while (i < ghosts.size())
3505     {
3506         leftovers.push_back(ghosts[i]);
3507         i++;
3508     }
3509 
3510     if (rewrite)
3511     {
3512         string permastore_file = _bones_permastore_file();
3513 
3514         // the following is to ensure that an old game doesn't overwrite a
3515         // permastore that has a version in the future relative to that game.
3516         {
3517             reader inf(permastore_file);
3518             if (inf.valid())
3519             {
3520                 inf.set_safe_read(true); // don't die on 0-byte bones
3521                 save_version version = read_ghost_header(inf);
3522                 if (version.valid() && version.is_future())
3523                 {
3524                     permastore_file = _old_bones_filename(permastore_file,
3525                                                     save_version::current());
3526                 }
3527                 inf.close();
3528             }
3529         }
3530 
3531         FILE *ghost_file = lk_open("wb", permastore_file);
3532 
3533         if (!ghost_file)
3534         {
3535             // this will fail silently if the lock fails, seems safest
3536             // TODO: better lock system for servers?
3537             _ghost_dprf("Could not open ghost permastore: %s",
3538                                                     permastore_file.c_str());
3539             return ghosts;
3540         }
3541 
3542         _ghost_dprf("Rewriting ghost permastore %s with %u ghosts",
3543                     permastore_file.c_str(), (unsigned int) permastore.size());
3544         writer outw(permastore_file, ghost_file);
3545         write_ghost_version(outw);
3546         tag_write_ghosts(outw, permastore);
3547 
3548         lk_close(ghost_file);
3549     }
3550     return leftovers;
3551 }
3552 
3553 /**
3554  * Attempt to save all ghosts from the current level.
3555  *
3556  * Including the player, if they're not undead. Doesn't save ghosts from D:1-2
3557  * or Temple.
3558  *
3559  * @param force   Forces ghost generation even in otherwise-disallowed levels.
3560  **/
save_ghosts(const vector<ghost_demon> & ghosts,bool force,bool use_store)3561 void save_ghosts(const vector<ghost_demon> &ghosts, bool force, bool use_store)
3562 {
3563     // n.b. this is not called in the normal course of events for wizmode
3564     // chars, so for debugging anything to do with deaths in wizmode, you will
3565     // need to edit a conditional at the end of ouch.cc:ouch.
3566     _ghost_dprf("Trying to save ghosts.");
3567     if (ghosts.empty())
3568     {
3569         _ghost_dprf("Could not find any ghosts for this level to save.");
3570         return;
3571     }
3572 
3573     if (!force && !ghost_demon::ghost_eligible())
3574     {
3575         _ghost_dprf("No eligible ghosts.");
3576         return;
3577     }
3578 
3579     vector<ghost_demon> leftovers;
3580     if (use_store)
3581         leftovers = _update_permastore(ghosts);
3582     else
3583         leftovers = ghosts;
3584     if (leftovers.size() == 0)
3585         return;
3586 
3587     if (_list_bones().size() >= static_cast<size_t>(GHOST_LIMIT))
3588     {
3589         _ghost_dprf("Too many ghosts for this level already!");
3590         return;
3591     }
3592 
3593     string g_file_name = "";
3594     FILE* ghost_file = _make_bones_file(&g_file_name);
3595 
3596     if (!ghost_file)
3597     {
3598         _ghost_dprf("Could not open file to save ghosts.");
3599         return;
3600     }
3601 
3602     writer outw(g_file_name, ghost_file);
3603 
3604     write_ghost_version(outw);
3605     tag_write_ghosts(outw, leftovers);
3606 
3607     lk_close(ghost_file);
3608 
3609     _ghost_dprf("Saved ghosts (%s).", g_file_name.c_str());
3610 }
3611 
3612 ////////////////////////////////////////////////////////////////////////////
3613 // Locking
3614 
lock_file_handle(FILE * handle,bool write)3615 bool lock_file_handle(FILE *handle, bool write)
3616 {
3617     return lock_file(fileno(handle), write, true);
3618 }
3619 
unlock_file_handle(FILE * handle)3620 bool unlock_file_handle(FILE *handle)
3621 {
3622     return unlock_file(fileno(handle));
3623 }
3624 
3625 /**
3626  * Attempts to open & lock a file.
3627  *
3628  * @param mode      The file access mode. ('r', 'ab+', etc)
3629  * @param file      The path to the file to be opened.
3630  * @return          A handle for the specified file, if successful; else nullptr.
3631  */
lk_open(const char * mode,const string & file)3632 FILE *lk_open(const char *mode, const string &file)
3633 {
3634     ASSERT(mode);
3635 
3636     FILE *handle = fopen_u(file.c_str(), mode);
3637     if (!handle)
3638         return nullptr;
3639 
3640     const bool write_lock = mode[0] != 'r' || strchr(mode, '+');
3641     if (!lock_file_handle(handle, write_lock))
3642     {
3643         mprf(MSGCH_ERROR, "ERROR: Could not lock file %s", file.c_str());
3644         fclose(handle);
3645         handle = nullptr;
3646     }
3647 
3648     return handle;
3649 }
3650 
3651 /**
3652  * Attempts to open and lock a file for exclusive write access; fails if
3653  * the file already exists.
3654  *
3655  * @param file The path to the file to be opened.
3656  * @return     A locked file handle for the specified file, if
3657  *             successful; else nullptr.
3658  */
lk_open_exclusive(const string & file)3659 FILE *lk_open_exclusive(const string &file)
3660 {
3661     int fd = open_u(file.c_str(), O_WRONLY|O_BINARY|O_EXCL|O_CREAT, 0666);
3662     if (fd < 0)
3663         return nullptr;
3664 
3665     if (!lock_file(fd, true))
3666     {
3667         mprf(MSGCH_ERROR, "ERROR: Could not lock file %s", file.c_str());
3668         close(fd);
3669         return nullptr;
3670     }
3671 
3672     return fdopen(fd, "wb");
3673 }
3674 
lk_close(FILE * handle)3675 void lk_close(FILE *handle)
3676 {
3677     if (handle == nullptr || handle == stdin)
3678         return;
3679 
3680     unlock_file_handle(handle);
3681 
3682     // actually close
3683     fclose(handle);
3684 }
3685 
3686 /////////////////////////////////////////////////////////////////////////////
3687 // file_lock
3688 //
3689 // Locks a named file (usually an empty lock file), creating it if necessary.
3690 
file_lock(const string & s,const char * _mode,bool die_on_fail)3691 file_lock::file_lock(const string &s, const char *_mode, bool die_on_fail)
3692     : handle(nullptr), mode(_mode), filename(s)
3693 {
3694     if (!(handle = lk_open(mode, filename)) && die_on_fail)
3695         end(1, true, "Unable to open lock file \"%s\"", filename.c_str());
3696 }
3697 
~file_lock()3698 file_lock::~file_lock()
3699 {
3700     if (handle)
3701         lk_close(handle);
3702 }
3703 
3704 /////////////////////////////////////////////////////////////////////////////
3705 
fopen_replace(const char * name)3706 FILE *fopen_replace(const char *name)
3707 {
3708     int fd;
3709 
3710     // Stave off symlink attacks. Races will be handled with O_EXCL.
3711     unlink_u(name);
3712     fd = open_u(name, O_CREAT|O_EXCL|O_WRONLY, 0666);
3713     if (fd == -1)
3714         return 0;
3715     return fdopen(fd, "w");
3716 }
3717 
3718 // Returns the size of the opened file with the give FILE* handle.
file_size(FILE * handle)3719 off_t file_size(FILE *handle)
3720 {
3721 #ifdef __ANDROID__
3722     off_t pos = ftello(handle);
3723     if (fseeko(handle, 0, SEEK_END) < 0)
3724         return 0;
3725     off_t ret = ftello(handle);
3726     fseeko(handle, pos, SEEK_SET);
3727     return ret;
3728 #else
3729     struct stat fs;
3730     const int err = fstat(fileno(handle), &fs);
3731     return err? 0 : fs.st_size;
3732 #endif
3733 }
3734 
get_title_files()3735 vector<string> get_title_files()
3736 {
3737     vector<string> titles;
3738     for (const string &dir : _get_base_dirs())
3739         for (const string &file : get_dir_files_sorted(dir))
3740             if (file.substr(0, 6) == "title_")
3741                 titles.push_back(file);
3742     return titles;
3743 }
3744