1 /*
2    Copyright (C) 2003 - 2018 by David White <dave@whitevine.net>
3    Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY.
11 
12    See the COPYING file for more details.
13 */
14 
15 #define GETTEXT_DOMAIN "wesnoth-lib"
16 
17 #include "game_board.hpp"
18 #include "game_display.hpp"
19 #include "preferences/game.hpp"
20 #include "gettext.hpp"
21 #include "lexical_cast.hpp"
22 #include "log.hpp"
23 #include "map/map.hpp"
24 #include "serialization/string_utils.hpp"
25 #include "serialization/unicode_cast.hpp"
26 #include "map_settings.hpp"
27 #include "units/unit.hpp"
28 #include "units/map.hpp"
29 #include "wml_exception.hpp"
30 
31 #include <cassert>
32 
33 static lg::log_domain log_config("config");
34 #define ERR_CFG LOG_STREAM(err , log_config)
35 
36 using acquaintances_map = std::map<std::string, preferences::acquaintance>;
37 
38 namespace {
39 
40 bool message_private_on = false;
41 
42 bool haloes = true;
43 
44 std::map<std::string, std::set<std::string>> completed_campaigns;
45 std::set<std::string> encountered_units_set;
46 std::set<t_translation::terrain_code> encountered_terrains_set;
47 
48 std::map<std::string, std::vector<std::string>> history_map;
49 
50 acquaintances_map acquaintances;
51 
52 std::vector<std::string> mp_modifications;
53 bool mp_modifications_initialized = false;
54 std::vector<std::string> sp_modifications;
55 bool sp_modifications_initialized = false;
56 
57 config option_values;
58 bool options_initialized = false;
59 
60 bool authenticated = false;
61 
initialize_modifications(bool mp=true)62 void initialize_modifications(bool mp = true)
63 {
64 	if (mp) {
65 		mp_modifications = utils::split(preferences::get("mp_modifications"), ',');
66 		mp_modifications_initialized = true;
67 	} else {
68 		sp_modifications = utils::split(preferences::get("sp_modifications"), ',');
69 		sp_modifications_initialized = true;
70 	}
71 }
72 
73 } // anon namespace
74 
75 namespace preferences {
76 
77 
manager()78 manager::manager() :
79 	base()
80 {
81 	set_music_volume(music_volume());
82 	set_sound_volume(sound_volume());
83 
84 	set_show_haloes(preferences::get("show_haloes", true));
85 	if (!preferences::get("remember_timer_settings", false)) {
86 		preferences::erase("mp_countdown_init_time");
87 		preferences::erase("mp_countdown_reservoir_time");
88 		preferences::erase("mp_countdown_turn_bonus");
89 		preferences::erase("mp_countdown_action_bonus");
90 	}
91 
92 	// We save the password encrypted now. Erase any saved passwords in the prefs file.
93 	preferences::erase("password");
94 	preferences::erase("password_is_wrapped");
95 
96 	// TODO: remove when we re-enable font scaling configuration.
97 	preferences::erase("font_scale");
98 
99 	/*
100 	completed_campaigns = "A,B,C"
101 	[completed_campaigns]
102 		[campaign]
103 			name = "A"
104 			difficulty_levels = "EASY,MEDIUM"
105 		[/campaign]
106 	[/completed_campaigns]
107 	*/
108 	for (const std::string &c : utils::split(preferences::get("completed_campaigns"))) {
109 		completed_campaigns[c]; // create the elements
110 	}
111 	if (const config &ccc = preferences::get_child("completed_campaigns")) {
112 		for (const config &cc : ccc.child_range("campaign")) {
113 			std::set<std::string> &d = completed_campaigns[cc["name"]];
114 			std::vector<std::string> nd = utils::split(cc["difficulty_levels"]);
115 			std::copy(nd.begin(), nd.end(), std::inserter(d, d.begin()));
116 		}
117 	}
118 
119 	const std::vector<std::string> v (utils::split(preferences::get("encountered_units")));
120 	encountered_units_set.insert(v.begin(), v.end());
121 
122 	const t_translation::ter_list terrain (t_translation::read_list(preferences::get("encountered_terrain_list")));
123 	encountered_terrains_set.insert(terrain.begin(), terrain.end());
124 
125 	if (const config &history = preferences::get_child("history"))
126 	{
127 /* Structure of the history
128 	[history]
129 		[history_id]
130 			[line]
131 				message = foobar
132 			[/line]
133 */
134 		for (const config::any_child &h : history.all_children_range())
135 		{
136 			for (const config &l : h.cfg.child_range("line")) {
137 				history_map[h.key].push_back(l["message"]);
138 			}
139 		}
140 	}
141 }
142 
~manager()143 manager::~manager()
144 {
145 	config campaigns;
146 	typedef const std::pair<std::string, std::set<std::string>> cc_elem;
147 	for (cc_elem &elem : completed_campaigns) {
148 		config cmp;
149 		cmp["name"] = elem.first;
150 		cmp["difficulty_levels"] = utils::join(elem.second);
151 		campaigns.add_child("campaign", cmp);
152 	}
153 	preferences::set_child("completed_campaigns", campaigns);
154 	std::vector<std::string> v (encountered_units_set.begin(), encountered_units_set.end());
155 	preferences::set("encountered_units", utils::join(v));
156 	t_translation::ter_list terrain (encountered_terrains_set.begin(), encountered_terrains_set.end());
157 	preferences::set("encountered_terrain_list", t_translation::write_list(terrain));
158 
159 /* Structure of the history
160 	[history]
161 		[history_id]
162 			[line]
163 				message = foobar
164 			[/line]
165 */
166 	config history;
167 	typedef std::pair<std::string, std::vector<std::string>> hack;
168 	for (const hack& history_id : history_map) {
169 
170 		config history_id_cfg; // [history_id]
171 		for (const std::string& line : history_id.second) {
172 			config cfg; // [line]
173 
174 			cfg["message"] = line;
175 			history_id_cfg.add_child("line", std::move(cfg));
176 		}
177 
178 		history.add_child(history_id.first, history_id_cfg);
179 	}
180 	preferences::set_child("history", history);
181 
182 	history_map.clear();
183 	encountered_units_set.clear();
184 	encountered_terrains_set.clear();
185 }
186 
is_authenticated()187 bool is_authenticated() {
188 	return authenticated;
189 }
190 
parse_admin_authentication(const std::string & sender,const std::string & message)191 void parse_admin_authentication(const std::string& sender, const std::string& message) {
192 	if(sender != "server") return;
193 	if(message.compare(0, 43, "You are now recognized as an administrator.") == 0) {
194 		authenticated = true;
195 	} else if(message.compare(0, 50, "You are no longer recognized as an administrator.") == 0) {
196 		authenticated = false;
197 	}
198 }
199 
admin_authentication_reset()200 admin_authentication_reset::admin_authentication_reset()
201 {
202 }
203 
~admin_authentication_reset()204 admin_authentication_reset::~admin_authentication_reset()
205 {
206 	authenticated = false;
207 }
208 
load_acquaintances()209 static void load_acquaintances() {
210 	if(acquaintances.empty()) {
211 		for (const config &acfg : preferences::get_prefs()->child_range("acquaintance")) {
212 			acquaintance ac = acquaintance(acfg);
213 			acquaintances[ac.get_nick()] = ac;
214 		}
215 	}
216 }
217 
save_acquaintances()218 static void save_acquaintances()
219 {
220 	config *cfg = preferences::get_prefs();
221 	cfg->clear_children("acquaintance");
222 
223 	for(std::map<std::string, acquaintance>::iterator i = acquaintances.begin();
224 			i != acquaintances.end(); ++i)
225 	{
226 		config& item = cfg->add_child("acquaintance");
227 		i->second.save(item);
228 	}
229 }
230 
get_acquaintances()231 const std::map<std::string, acquaintance> & get_acquaintances() {
232 	load_acquaintances();
233 	return acquaintances;
234 }
235 
236 //returns acquaintances in the form nick => notes where the status = filter
get_acquaintances_nice(const std::string & filter)237 std::map<std::string, std::string> get_acquaintances_nice(const std::string& filter) {
238 	load_acquaintances();
239 	std::map<std::string, std::string> ac_nice;
240 
241 	for(std::map<std::string, acquaintance>::iterator i = acquaintances.begin(); i != acquaintances.end(); ++i)
242 	{
243 		if(i->second.get_status() == filter) {
244 			ac_nice[i->second.get_nick()] = i->second.get_notes();
245 		}
246 	}
247 
248 	return ac_nice;
249 }
250 
add_acquaintance(const std::string & nick,const std::string & mode,const std::string & notes)251 std::pair<preferences::acquaintance*, bool> add_acquaintance(const std::string& nick, const std::string& mode, const std::string& notes)
252 {
253 	if(!utils::isvalid_wildcard(nick)) {
254 		return std::make_pair(nullptr, false);
255 	}
256 
257 	preferences::acquaintance new_entry(nick, mode, notes);
258 
259 	acquaintances_map::iterator iter;
260 	bool success;
261 
262 	std::tie(iter, success) = acquaintances.emplace(nick, new_entry);
263 
264 	if(!success) {
265 		iter->second = new_entry;
266 	}
267 
268 	save_acquaintances();
269 
270 	return std::make_pair(&iter->second, success);
271 }
272 
remove_acquaintance(const std::string & nick)273 bool remove_acquaintance(const std::string& nick) {
274 	std::map<std::string, acquaintance>::iterator i = acquaintances.find(nick);
275 
276 	//nick might include the notes, depending on how we're removing
277 	if(i == acquaintances.end()) {
278 		size_t pos = nick.find_first_of(' ');
279 
280 		if(pos != std::string::npos) {
281 			i = acquaintances.find(nick.substr(0, pos));
282 		}
283 	}
284 
285 	if(i == acquaintances.end()) {
286 		return false;
287 	}
288 
289 	acquaintances.erase(i);
290 	save_acquaintances();
291 
292 	return true;
293 }
294 
is_friend(const std::string & nick)295 bool is_friend(const std::string& nick)
296 {
297 	load_acquaintances();
298 	const std::map<std::string, acquaintance
299 			>::const_iterator it = acquaintances.find(nick);
300 
301 	if(it == acquaintances.end()) {
302 		return false;
303 	} else {
304 		return it->second.get_status() == "friend";
305 	}
306 }
307 
is_ignored(const std::string & nick)308 bool is_ignored(const std::string& nick)
309 {
310 	load_acquaintances();
311 	const std::map<std::string, acquaintance
312 			>::const_iterator it = acquaintances.find(nick);
313 
314 	if(it == acquaintances.end()) {
315 		return false;
316 	} else {
317 		return it->second.get_status() == "ignore";
318 	}
319 }
320 
add_completed_campaign(const std::string & campaign_id,const std::string & difficulty_level)321 void add_completed_campaign(const std::string &campaign_id, const std::string &difficulty_level) {
322 	completed_campaigns[campaign_id].insert(difficulty_level);
323 }
324 
is_campaign_completed(const std::string & campaign_id)325 bool is_campaign_completed(const std::string& campaign_id) {
326 	return completed_campaigns.count(campaign_id) != 0;
327 }
328 
is_campaign_completed(const std::string & campaign_id,const std::string & difficulty_level)329 bool is_campaign_completed(const std::string& campaign_id, const std::string &difficulty_level) {
330 	std::map<std::string, std::set<std::string>>::iterator it = completed_campaigns.find(campaign_id);
331 	return it == completed_campaigns.end() ? false : it->second.count(difficulty_level) != 0;
332 }
333 
parse_should_show_lobby_join(const std::string & sender,const std::string & message)334 bool parse_should_show_lobby_join(const std::string &sender, const std::string &message)
335 {
336 	// If it's actually not a lobby join or leave message return true (show it).
337 	if (sender != "server") return true;
338 	std::string::size_type pos = message.find(" has logged into the lobby");
339 	if (pos == std::string::npos){
340 		pos = message.find(" has disconnected");
341 		if (pos == std::string::npos) return true;
342 	}
343 	int lj = lobby_joins();
344 	if (lj == SHOW_NONE) return false;
345 	if (lj == SHOW_ALL) return true;
346 	return is_friend(message.substr(0, pos));
347 }
348 
lobby_joins()349 int lobby_joins()
350 {
351 	std::string pref = preferences::get("lobby_joins");
352 	if (pref == "friends") {
353 		return SHOW_FRIENDS;
354 	} else if (pref == "all") {
355 		return SHOW_ALL;
356 	} else if (pref == "none") {
357 		return SHOW_NONE;
358 	} else {
359 		return SHOW_FRIENDS;
360 	}
361 }
362 
363 
_set_lobby_joins(int show)364 void _set_lobby_joins(int show)
365 {
366 	if (show == SHOW_FRIENDS) {
367 		preferences::set("lobby_joins", "friends");
368 	} else if (show == SHOW_ALL) {
369 		preferences::set("lobby_joins", "all");
370 	} else if (show == SHOW_NONE) {
371 		preferences::set("lobby_joins", "none");
372 	}
373 }
374 
server_list()375 const std::vector<game_config::server_info>& server_list()
376 {
377 	static std::vector<game_config::server_info> pref_servers;
378 	if(pref_servers.empty()) {
379 		std::vector<game_config::server_info> &game_servers = game_config::server_list;
380 		VALIDATE(!game_servers.empty(), _("No server has been defined."));
381 		pref_servers.insert(pref_servers.begin(), game_servers.begin(), game_servers.end());
382 		for(const config &server : get_prefs()->child_range("server")) {
383 			game_config::server_info sinf;
384 			sinf.name = server["name"].str();
385 			sinf.address = server["address"].str();
386 			pref_servers.push_back(sinf);
387 		}
388 	}
389 	return pref_servers;
390 }
391 
network_host()392 std::string network_host()
393 {
394 	const std::string res = preferences::get("host");
395 	if(res.empty()) {
396 		return server_list().front().address;
397 	} else {
398 		return res;
399 	}
400 }
401 
set_network_host(const std::string & host)402 void set_network_host(const std::string& host)
403 {
404 	preferences::set("host", host);
405 }
406 
campaign_server()407 std::string campaign_server()
408 {
409 	if(!preferences::get("campaign_server").empty()) {
410 		return preferences::get("campaign_server");
411 	} else {
412 		return "add-ons.wesnoth.org";
413 	}
414 }
415 
set_campaign_server(const std::string & host)416 void set_campaign_server(const std::string& host)
417 {
418 	preferences::set("campaign_server", host);
419 }
420 
turn_dialog()421 bool turn_dialog()
422 {
423 	return preferences::get("turn_dialog", false);
424 }
425 
set_turn_dialog(bool ison)426 void set_turn_dialog(bool ison)
427 {
428 	preferences::set("turn_dialog", ison);
429 }
430 
enable_whiteboard_mode_on_start()431 bool enable_whiteboard_mode_on_start()
432 {
433 	return preferences::get("enable_planning_mode_on_start", false);
434 }
435 
set_enable_whiteboard_mode_on_start(bool value)436 void set_enable_whiteboard_mode_on_start(bool value)
437 {
438 	preferences::set("enable_planning_mode_on_start", value);
439 }
440 
hide_whiteboard()441 bool hide_whiteboard()
442 {
443 	return preferences::get("hide_whiteboard", false);
444 }
445 
set_hide_whiteboard(bool value)446 void set_hide_whiteboard(bool value)
447 {
448 	preferences::set("hide_whiteboard", value);
449 }
450 
show_combat()451 bool show_combat()
452 {
453 	return preferences::get("show_combat", true);
454 }
455 
allow_observers()456 bool allow_observers()
457 {
458 	return preferences::get("allow_observers", true);
459 }
460 
set_allow_observers(bool value)461 void set_allow_observers(bool value)
462 {
463 	preferences::set("allow_observers", value);
464 }
465 
registered_users_only()466 bool registered_users_only()
467 {
468 	return preferences::get("registered_users_only", false);
469 }
470 
set_registered_users_only(bool value)471 void set_registered_users_only(bool value)
472 {
473 	preferences::set("registered_users_only", value);
474 }
475 
shuffle_sides()476 bool shuffle_sides()
477 {
478 	return preferences::get("shuffle_sides", false);
479 }
480 
set_shuffle_sides(bool value)481 void set_shuffle_sides(bool value)
482 {
483 	preferences::set("shuffle_sides", value);
484 }
485 
random_faction_mode()486 std::string random_faction_mode(){
487 	return preferences::get("random_faction_mode");
488 }
489 
set_random_faction_mode(const std::string & value)490 void set_random_faction_mode(const std::string & value) {
491 	preferences::set("random_faction_mode", value);
492 }
493 
use_map_settings()494 bool use_map_settings()
495 {
496 	return preferences::get("mp_use_map_settings", true);
497 }
498 
set_use_map_settings(bool value)499 void set_use_map_settings(bool value)
500 {
501 	preferences::set("mp_use_map_settings", value);
502 }
503 
mp_server_warning_disabled()504 int mp_server_warning_disabled()
505 {
506 	return lexical_cast_default<int>(preferences::get("mp_server_warning_disabled"), 0);
507 }
508 
set_mp_server_warning_disabled(int value)509 void set_mp_server_warning_disabled(int value)
510 {
511 	preferences::set("mp_server_warning_disabled", value);
512 }
513 
set_mp_server_program_name(const std::string & path)514 void set_mp_server_program_name(const std::string& path)
515 {
516 	if (path.empty())
517 	{
518 		preferences::clear("mp_server_program_name");
519 	}
520 	else
521 	{
522 		preferences::set("mp_server_program_name", path);
523 	}
524 }
525 
get_mp_server_program_name()526 std::string get_mp_server_program_name()
527 {
528 	return preferences::get("mp_server_program_name");
529 }
530 
random_start_time()531 bool random_start_time()
532 {
533 	return preferences::get("mp_random_start_time", true);
534 }
535 
set_random_start_time(bool value)536 void set_random_start_time(bool value)
537 {
538 	preferences::set("mp_random_start_time", value);
539 }
540 
fog()541 bool fog()
542 {
543 	return preferences::get("mp_fog", true);
544 }
545 
set_fog(bool value)546 void set_fog(bool value)
547 {
548 	preferences::set("mp_fog", value);
549 }
550 
shroud()551 bool shroud()
552 {
553 	return preferences::get("mp_shroud", false);
554 }
555 
set_shroud(bool value)556 void set_shroud(bool value)
557 {
558 	preferences::set("mp_shroud", value);
559 }
560 
turns()561 int turns()
562 {
563 	return settings::get_turns(preferences::get("mp_turns"));
564 }
565 
set_turns(int value)566 void set_turns(int value)
567 {
568 	preferences::set("mp_turns", value);
569 }
570 
options()571 const config& options()
572 {
573 	if (options_initialized) {
574 		return option_values;
575 	}
576 
577 	if (!preferences::get_child("options")) {
578 		// It may be an invalid config, which would cause problems in
579 		// multiplayer_create, so let's replace it with an empty but valid
580 		// config
581 		option_values.clear();
582 	} else {
583 		option_values = preferences::get_child("options");
584 	}
585 
586 	options_initialized = true;
587 
588 	return option_values;
589 }
590 
set_options(const config & values)591 void set_options(const config& values)
592 {
593 	preferences::set_child("options", values);
594 	options_initialized = false;
595 }
596 
skip_mp_replay()597 bool skip_mp_replay()
598 {
599 	return preferences::get("skip_mp_replay", false);
600 }
601 
set_skip_mp_replay(bool value)602 void set_skip_mp_replay(bool value)
603 {
604 	preferences::set("skip_mp_replay", value);
605 }
606 
blindfold_replay()607 bool blindfold_replay()
608 {
609 	return preferences::get("blindfold_replay", false);
610 }
611 
set_blindfold_replay(bool value)612 void set_blindfold_replay(bool value)
613 {
614 	preferences::set("blindfold_replay", value);
615 }
616 
countdown()617 bool countdown()
618 {
619 	return preferences::get("mp_countdown", false);
620 }
621 
set_countdown(bool value)622 void set_countdown(bool value)
623 {
624 	preferences::set("mp_countdown", value);
625 }
626 
countdown_init_time()627 int countdown_init_time()
628 {
629 	return utils::clamp<int>(
630 		lexical_cast_default<int>(preferences::get("mp_countdown_init_time"), 270), 0, 1500);
631 }
632 
set_countdown_init_time(int value)633 void set_countdown_init_time(int value)
634 {
635 	preferences::set("mp_countdown_init_time", value);
636 }
637 
countdown_reservoir_time()638 int countdown_reservoir_time()
639 {
640 	return utils::clamp<int>(
641 		lexical_cast_default<int>(preferences::get("mp_countdown_reservoir_time"), 330), 30, 1500);
642 }
643 
set_countdown_reservoir_time(int value)644 void set_countdown_reservoir_time(int value)
645 {
646 	preferences::set("mp_countdown_reservoir_time", value);
647 }
648 
countdown_turn_bonus()649 int countdown_turn_bonus()
650 {
651 	return utils::clamp<int>(
652 		lexical_cast_default<int>(preferences::get("mp_countdown_turn_bonus"), 60), 0, 300);
653 }
654 
set_countdown_turn_bonus(int value)655 void set_countdown_turn_bonus(int value)
656 {
657 	preferences::set("mp_countdown_turn_bonus", value);
658 }
659 
countdown_action_bonus()660 int countdown_action_bonus()
661 {
662 	return utils::clamp<int>(
663 		lexical_cast_default<int>(preferences::get("mp_countdown_action_bonus"), 13), 0, 30);
664 }
665 
set_countdown_action_bonus(int value)666 void set_countdown_action_bonus(int value)
667 {
668 	preferences::set("mp_countdown_action_bonus", value);
669 }
670 
village_gold()671 int village_gold()
672 {
673 	return settings::get_village_gold(preferences::get("mp_village_gold"));
674 }
675 
set_village_gold(int value)676 void set_village_gold(int value)
677 {
678 	preferences::set("mp_village_gold", value);
679 }
680 
village_support()681 int village_support()
682 {
683 	return settings::get_village_support(preferences::get("mp_village_support"));
684 }
685 
set_village_support(int value)686 void set_village_support(int value)
687 {
688 	preferences::set("mp_village_support", std::to_string(value));
689 }
690 
xp_modifier()691 int xp_modifier()
692 {
693 	return settings::get_xp_modifier(preferences::get("mp_xp_modifier"));
694 }
695 
set_xp_modifier(int value)696 void set_xp_modifier(int value)
697 {
698 	preferences::set("mp_xp_modifier", value);
699 }
700 
era()701 std::string era()
702 {
703 	return preferences::get("mp_era");
704 }
705 
set_era(const std::string & value)706 void set_era(const std::string& value)
707 {
708 	preferences::set("mp_era", value);
709 }
710 
level()711 std::string level()
712 {
713 	return preferences::get("mp_level");
714 }
715 
set_level(const std::string & value)716 void set_level(const std::string& value)
717 {
718 	preferences::set("mp_level", value);
719 }
720 
level_type()721 int level_type()
722 {
723 	return lexical_cast_default<int>(preferences::get("mp_level_type"), 0);
724 }
725 
set_level_type(int value)726 void set_level_type(int value)
727 {
728 	preferences::set("mp_level_type", value);
729 }
730 
modifications(bool mp)731 const std::vector<std::string>& modifications(bool mp)
732 {
733 	if ((!mp_modifications_initialized && mp) || (!sp_modifications_initialized && !mp))
734 		initialize_modifications(mp);
735 
736 	return mp ? mp_modifications : sp_modifications;
737 }
738 
set_modifications(const std::vector<std::string> & value,bool mp)739 void set_modifications(const std::vector<std::string>& value, bool mp)
740 {
741 	if (mp) {
742 		preferences::set("mp_modifications", utils::join(value, ","));
743 		mp_modifications_initialized = false;
744 	} else {
745 		preferences::set("sp_modifications", utils::join(value, ","));
746 		sp_modifications_initialized = false;
747 	}
748 
749 }
750 
skip_ai_moves()751 bool skip_ai_moves()
752 {
753 	return preferences::get("skip_ai_moves", false);
754 }
755 
set_skip_ai_moves(bool value)756 void set_skip_ai_moves(bool value)
757 {
758 	preferences::set("skip_ai_moves", value);
759 }
760 
set_show_side_colors(bool value)761 void set_show_side_colors(bool value)
762 {
763 	preferences::set("show_side_colors", value);
764 }
765 
show_side_colors()766 bool show_side_colors()
767 {
768 	return preferences::get("show_side_colors", true);
769 }
770 
set_save_replays(bool value)771 void set_save_replays(bool value)
772 {
773 	preferences::set("save_replays", value);
774 }
775 
save_replays()776 bool save_replays()
777 {
778 	return preferences::get("save_replays", true);
779 }
780 
set_delete_saves(bool value)781 void set_delete_saves(bool value)
782 {
783 	preferences::set("delete_saves", value);
784 }
785 
delete_saves()786 bool delete_saves()
787 {
788 	return preferences::get("delete_saves", false);
789 }
790 
set_ask_delete_saves(bool value)791 void set_ask_delete_saves(bool value)
792 {
793 	preferences::set("ask_delete", value);
794 }
795 
ask_delete_saves()796 bool ask_delete_saves()
797 {
798 	return preferences::get("ask_delete", true);
799 }
800 
set_interrupt_when_ally_sighted(bool value)801 void set_interrupt_when_ally_sighted(bool value)
802 {
803 	preferences::set("ally_sighted_interrupts", value);
804 }
805 
interrupt_when_ally_sighted()806 bool interrupt_when_ally_sighted()
807 {
808 	return preferences::get("ally_sighted_interrupts", true);
809 }
810 
autosavemax()811 int autosavemax()
812 {
813 	return lexical_cast_default<int>(preferences::get("auto_save_max"), 10);
814 }
815 
set_autosavemax(int value)816 void set_autosavemax(int value)
817 {
818 	preferences::set("auto_save_max", value);
819 }
820 
theme()821 std::string theme()
822 {
823 	if(CVideo::get_singleton().non_interactive()) {
824 		static const std::string null_theme = "null";
825 		return null_theme;
826 	}
827 
828 	std::string res = preferences::get("theme");
829 	if(res.empty()) {
830 		return "Default";
831 	}
832 
833 	return res;
834 }
835 
set_theme(const std::string & theme)836 void set_theme(const std::string& theme)
837 {
838 	if(theme != "null") {
839 		preferences::set("theme", theme);
840 	}
841 }
842 
show_floating_labels()843 bool show_floating_labels()
844 {
845 	return preferences::get("floating_labels", true);
846 }
847 
set_show_floating_labels(bool value)848 void set_show_floating_labels(bool value)
849 {
850 	preferences::set("floating_labels", value);
851 }
852 
message_private()853 bool message_private()
854 {
855 	return message_private_on;
856 }
857 
set_message_private(bool value)858 void set_message_private(bool value)
859 {
860 	message_private_on = value;
861 }
862 
show_haloes()863 bool show_haloes()
864 {
865 	return haloes;
866 }
867 
set_show_haloes(bool value)868 void set_show_haloes(bool value)
869 {
870 	haloes = value;
871 	preferences::set("show_haloes", value);
872 }
873 
save_compression_format()874 compression::format save_compression_format()
875 {
876 	const std::string& choice =
877 		preferences::get("compress_saves");
878 
879 	// "yes" was used in 1.11.7 and earlier; the compress_saves
880 	// option used to be a toggle for gzip in those versions.
881 	if(choice.empty() || choice == "gzip" || choice == "yes") {
882 		return compression::GZIP;
883 	} else if(choice == "bzip2") {
884 		return compression::BZIP2;
885 	} else if(choice == "none" || choice == "no") { // see above
886 		return compression::NONE;
887 	} /*else*/
888 
889 	// In case the preferences file was created by a later version
890 	// supporting some algorithm we don't; although why would anyone
891 	// playing a game need more algorithms, really...
892 	return compression::GZIP;
893 }
894 
get_chat_timestamp(const time_t & t)895 std::string get_chat_timestamp(const time_t& t) {
896 	if (chat_timestamping()) {
897 		if(preferences::use_twelve_hour_clock_format() == false) {
898 			return lg::get_timestamp(t, _("[%H:%M]")) + " ";
899 		}
900 		else {
901 			return lg::get_timestamp(t, _("[%I:%M %p]")) + " ";
902 		}
903 	}
904 	return "";
905 }
906 
chat_timestamping()907 bool chat_timestamping() {
908 	return preferences::get("chat_timestamp", false);
909 }
910 
set_chat_timestamping(bool value)911 void set_chat_timestamping(bool value) {
912 	preferences::set("chat_timestamp", value);
913 }
914 
chat_lines()915 int chat_lines()
916 {
917 	return lexical_cast_default<int>(preferences::get("chat_lines"), 6);
918 }
919 
set_chat_lines(int lines)920 void set_chat_lines(int lines)
921 {
922 	preferences::set("chat_lines", lines);
923 }
924 
set_chat_message_aging(const int aging)925 void set_chat_message_aging(const int aging)
926 {
927 	preferences::set("chat_message_aging", aging);
928 }
929 
chat_message_aging()930 int chat_message_aging()
931 {
932 	return lexical_cast_default<int>(preferences::get("chat_message_aging"), 20);
933 }
934 
show_all_units_in_help()935 bool show_all_units_in_help() {
936 	return preferences::get("show_all_units_in_help", false);
937 }
938 
set_show_all_units_in_help(bool value)939 void set_show_all_units_in_help(bool value) {
940 	preferences::set("show_all_units_in_help", value);
941 }
942 
encountered_units()943 std::set<std::string> &encountered_units() {
944 	return encountered_units_set;
945 }
946 
encountered_terrains()947 std::set<t_translation::terrain_code> &encountered_terrains() {
948 	return encountered_terrains_set;
949 }
950 
custom_command()951 std::string custom_command() {
952 	return preferences::get("custom_command");
953 }
954 
set_custom_command(const std::string & command)955 void set_custom_command(const std::string& command) {
956 	preferences::set("custom_command", command);
957 }
958 
959 /**
960  * Returns a pointer to the history vector associated with given id
961  * making a new one if it doesn't exist.
962  *
963  * @todo FIXME only used for gui2. Could be used for the above histories.
964  */
get_history(const std::string & id)965 std::vector<std::string>* get_history(const std::string& id) {
966 	return &history_map[id];
967 }
968 
green_confirm()969 bool green_confirm()
970 {
971 	std::string confirmation = preferences::get("confirm_end_turn");
972 
973 	if (confirmation == "green" || confirmation == "yes")
974 		return true;
975 	return false;
976 }
977 
yellow_confirm()978 bool yellow_confirm()
979 {
980 	return preferences::get("confirm_end_turn") == "yellow";
981 }
982 
confirm_no_moves()983 bool confirm_no_moves()
984 {
985 	//This is very non-intrusive so it is on by default
986 	const std::string confirmation = preferences::get("confirm_end_turn");
987 	return confirmation == "no_moves" || confirmation.empty();
988 }
989 
990 
encounter_recruitable_units(const std::vector<team> & teams)991 void encounter_recruitable_units(const std::vector<team>& teams){
992 	for (std::vector<team>::const_iterator help_team_it = teams.begin();
993 		help_team_it != teams.end(); ++help_team_it) {
994 		help_team_it->log_recruitable();
995 		encountered_units_set.insert(help_team_it->recruits().begin(), help_team_it->recruits().end());
996 	}
997 }
998 
encounter_start_units(const unit_map & units)999 void encounter_start_units(const unit_map& units){
1000 	for (unit_map::const_iterator help_unit_it = units.begin();
1001 		 help_unit_it != units.end(); ++help_unit_it) {
1002 		encountered_units_set.insert(help_unit_it->type_id());
1003 	}
1004 }
1005 
encounter_recallable_units(const std::vector<team> & teams)1006 static void encounter_recallable_units(const std::vector<team>& teams){
1007 	for (const team& t : teams) {
1008 		for (const unit_const_ptr & u : t.recall_list()) {
1009 			encountered_units_set.insert(u->type_id());
1010 		}
1011 	}
1012 }
1013 
encounter_map_terrain(const gamemap & map)1014 void encounter_map_terrain(const gamemap& map)
1015 {
1016 	map.for_each_loc([&](const map_location& loc) {
1017 		const t_translation::terrain_code terrain = map.get_terrain(loc);
1018 		preferences::encountered_terrains().insert(terrain);
1019 		for (t_translation::terrain_code t : map.underlying_union_terrain(loc)) {
1020 			preferences::encountered_terrains().insert(t);
1021 		}
1022 	});
1023 }
1024 
encounter_all_content(const game_board & gameboard_)1025 void encounter_all_content(const game_board & gameboard_) {
1026 	preferences::encounter_recruitable_units(gameboard_.teams());
1027 	preferences::encounter_start_units(gameboard_.units());
1028 	preferences::encounter_recallable_units(gameboard_.teams());
1029 	preferences::encounter_map_terrain(gameboard_.map());
1030 }
1031 
load_from_config(const config & cfg)1032 void acquaintance::load_from_config(const config& cfg)
1033 {
1034 	nick_ = cfg["nick"].str();
1035 	status_ = cfg["status"].str();
1036 	notes_ = cfg["notes"].str();
1037 }
1038 
save(config & item)1039 void acquaintance::save(config& item)
1040 {
1041 	item["nick"] = nick_;
1042 	item["status"] = status_;
1043 	item["notes"] = notes_;
1044 }
1045 
1046 } // preferences namespace
1047