<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.wesnoth.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Res</id>
	<title>The Battle for Wesnoth Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.wesnoth.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Res"/>
	<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/Special:Contributions/Res"/>
	<updated>2026-04-11T16:03:06Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.31.16</generator>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_res&amp;diff=29332</id>
		<title>SummerOfCodeProposal res</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_res&amp;diff=29332"/>
		<updated>2009-03-27T13:56:18Z</updated>

		<summary type="html">&lt;p&gt;Res: /* Current status */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= A bit about me =&lt;br /&gt;
&lt;br /&gt;
My name is Frank Richter, currently studying Computer Sciences at the University of Jena (that's in Germany).&lt;br /&gt;
&lt;br /&gt;
As far as C++ is concerned, I program in it since at least seven years now. In my spare time I also develop for Crystal Space, an open source 3D engine. While I did a lot in the topics of realtime 3D, OpenGL, shaders and such, I also did (and do) 'low-level' things like cross-platform services and, last, but in this context here now certainly not least, matters of ''memory optimization''. &lt;br /&gt;
&lt;br /&gt;
= Current status =&lt;br /&gt;
&lt;br /&gt;
* Upon reading the blog post linked in the idea proposal my first thought was to use a proxy class for operator[]. Below a patch that implements it.&lt;br /&gt;
* I submitted a proposal via the Google SoC app. It contains some other information relevant for mentors/admins.&lt;br /&gt;
&lt;br /&gt;
== Proxy class patch ==&lt;br /&gt;
&lt;br /&gt;
This builds and, I believe, works, but has a number of not-so-nice issues:&lt;br /&gt;
* Some places store return values in &amp;lt;tt&amp;gt;t_string&amp;amp;&amp;lt;/tt&amp;gt;. The idea is to change these to &amp;lt;tt&amp;gt;config::proxy_string&amp;lt;/tt&amp;gt;, as that type should ideally behave like &amp;lt;tt&amp;gt;t_string&amp;amp;&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;s&amp;gt;&amp;lt;tt&amp;gt;config::proxy_string&amp;lt;/tt&amp;gt; can cast to both &amp;lt;tt&amp;gt;std::string&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;t_string&amp;lt;/tt&amp;gt;.&lt;br /&gt;
The first is necessary as &amp;lt;tt&amp;gt;t_string&amp;lt;/tt&amp;gt; can cast to it as well; the second is necessary to&lt;br /&gt;
support use of a &amp;lt;tt&amp;gt;config::proxy_string&amp;lt;/tt&amp;gt; where a &amp;lt;tt&amp;gt;const t_string&amp;amp;&amp;lt;/tt&amp;gt; is expected.&lt;br /&gt;
Unfortunately, this introduces an ambiguity in cases where a &amp;lt;tt&amp;gt;config::proxy_string&amp;lt;/tt&amp;gt; is passed to methods that can take either of &amp;lt;tt&amp;gt;std::string&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;t_string&amp;lt;/tt&amp;gt;. The ambiguity was solved in some places by using &amp;lt;tt&amp;gt;.str()&amp;lt;/tt&amp;gt;. It would also go away when &amp;lt;tt&amp;gt;proxy_string operator[]&amp;lt;/tt&amp;gt; is removed.&amp;lt;/s&amp;gt; Resolved differently, see comments on GNA.&lt;br /&gt;
* the &amp;lt;tt&amp;gt;variables_set&amp;lt;/tt&amp;gt; class has a member (&amp;lt;tt&amp;gt;get_variable_const()&amp;lt;/tt&amp;gt;) that returns a &amp;lt;tt&amp;gt;t_string&amp;amp;&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;game_state&amp;lt;/tt&amp;gt; descends from this class; it's &amp;lt;tt&amp;gt;get_variable_const()&amp;lt;/tt&amp;gt; implementation supposedly returns a value from a &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;. To ensure the ref is valid, the value as a &amp;lt;tt&amp;gt;t_string&amp;lt;/tt&amp;gt; is stored in a map. This is clearly not ideal.&lt;br /&gt;
&lt;br /&gt;
The patch was submitted to the patch tracker: https://gna.org/patch/index.php?1139&lt;br /&gt;
&lt;br /&gt;
= Next (technically, first) Steps =&lt;br /&gt;
&lt;br /&gt;
* Get rid of &amp;lt;tt&amp;gt;t_string&amp;amp; operator[]&amp;lt;/tt&amp;gt; - could be a proxy class, as above, or like in the initial blog post, a setter function. A way in-between could be to have the proxy class for convenient migration, but mark is a deprecated; instead, promote the usage of the setter. Cases where the proxy class actually introduces ugliness should be fixed manually.&lt;br /&gt;
* Assuming that only a limited set of keys is used all keys can be stored in a global &amp;quot;add-only&amp;quot; pool. Individual &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; instances would only the pointers to the global keys.&lt;br /&gt;
* For values consider changing &amp;lt;tt&amp;gt;t_string&amp;lt;/tt&amp;gt; to be backed by a string that is &amp;quot;copy on write&amp;quot;, so a single copy is used unless the string is manipulated. silene suggested to store short, untranslatable values inside &amp;lt;tt&amp;gt;t_string&amp;lt;/tt&amp;gt; directly to use the &amp;quot;16 or 24 bytes&amp;quot; it takes up anyway.&lt;/div&gt;</summary>
		<author><name>Res</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_res&amp;diff=29138</id>
		<title>SummerOfCodeProposal res</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_res&amp;diff=29138"/>
		<updated>2009-03-23T16:46:04Z</updated>

		<summary type="html">&lt;p&gt;Res: /* Next (technically, first) Steps */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= A bit about me =&lt;br /&gt;
&lt;br /&gt;
My name is Frank Richter, currently studying Computer Sciences at the University of Jena (that's in Germany).&lt;br /&gt;
&lt;br /&gt;
As far as C++ is concerned, I program in it since at least seven years now. In my spare time I also develop for Crystal Space, an open source 3D engine. While I did a lot in the topics of realtime 3D, OpenGL, shaders and such, I also did (and do) 'low-level' things like cross-platform services and, last, but in this context here now certainly not least, matters of ''memory optimization''. &lt;br /&gt;
&lt;br /&gt;
= Current status =&lt;br /&gt;
&lt;br /&gt;
* Upon reading the blog post linked in the idea proposal my first thought was to use a proxy class for operator[]. Below a patch that implements it.&lt;br /&gt;
&lt;br /&gt;
== Proxy class patch ==&lt;br /&gt;
&lt;br /&gt;
This builds and, I believe, works, but has a number of not-so-nice issues:&lt;br /&gt;
* Some places store return values in &amp;lt;tt&amp;gt;t_string&amp;amp;&amp;lt;/tt&amp;gt;. The idea is to change these to &amp;lt;tt&amp;gt;config::proxy_string&amp;lt;/tt&amp;gt;, as that type should ideally behave like &amp;lt;tt&amp;gt;t_string&amp;amp;&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;config::proxy_string&amp;lt;/tt&amp;gt; can cast to both &amp;lt;tt&amp;gt;std::string&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;t_string&amp;lt;/tt&amp;gt;.&lt;br /&gt;
The first is necessary as &amp;lt;tt&amp;gt;t_string&amp;lt;/tt&amp;gt; can cast to it as well; the second is necessary to&lt;br /&gt;
support use of a &amp;lt;tt&amp;gt;config::proxy_string&amp;lt;/tt&amp;gt; where a &amp;lt;tt&amp;gt;const t_string&amp;amp;&amp;lt;/tt&amp;gt; is expected.&lt;br /&gt;
Unfortunately, this introduces an ambiguity in cases where a &amp;lt;tt&amp;gt;config::proxy_string&amp;lt;/tt&amp;gt; is passed to methods that can take either of &amp;lt;tt&amp;gt;std::string&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;t_string&amp;lt;/tt&amp;gt;. The ambiguity was solved in some places by using &amp;lt;tt&amp;gt;.str()&amp;lt;/tt&amp;gt;. It would also go away when &amp;lt;tt&amp;gt;proxy_string operator[]&amp;lt;/tt&amp;gt; is removed.&lt;br /&gt;
* the &amp;lt;tt&amp;gt;variables_set&amp;lt;/tt&amp;gt; class has a member (&amp;lt;tt&amp;gt;get_variable_const()&amp;lt;/tt&amp;gt;) that returns a &amp;lt;tt&amp;gt;t_string&amp;amp;&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;game_state&amp;lt;/tt&amp;gt; descends from this class; it's &amp;lt;tt&amp;gt;get_variable_const()&amp;lt;/tt&amp;gt; implementation supposedly returns a value from a &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;. To ensure the ref is valid, the value as a &amp;lt;tt&amp;gt;t_string&amp;lt;/tt&amp;gt; is stored in a map. This is clearly not ideal.&lt;br /&gt;
&lt;br /&gt;
The patch was submitted to the patch tracker: https://gna.org/patch/index.php?1139&lt;br /&gt;
&lt;br /&gt;
= Next (technically, first) Steps =&lt;br /&gt;
&lt;br /&gt;
* Get rid of &amp;lt;tt&amp;gt;t_string&amp;amp; operator[]&amp;lt;/tt&amp;gt; - could be a proxy class, as above, or like in the initial blog post, a setter function. A way in-between could be to have the proxy class for convenient migration, but mark is a deprecated; instead, promote the usage of the setter. Cases where the proxy class actually introduces ugliness should be fixed manually.&lt;br /&gt;
* Assuming that only a limited set of keys is used all keys can be stored in a global &amp;quot;add-only&amp;quot; pool. Individual &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; instances would only the pointers to the global keys.&lt;br /&gt;
* For values consider changing &amp;lt;tt&amp;gt;t_string&amp;lt;/tt&amp;gt; to be backed by a string that is &amp;quot;copy on write&amp;quot;, so a single copy is used unless the string is manipulated. silene suggested to store short, untranslatable values inside &amp;lt;tt&amp;gt;t_string&amp;lt;/tt&amp;gt; directly to use the &amp;quot;16 or 24 bytes&amp;quot; it takes up anyway.&lt;/div&gt;</summary>
		<author><name>Res</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_res&amp;diff=29136</id>
		<title>SummerOfCodeProposal res</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_res&amp;diff=29136"/>
		<updated>2009-03-23T14:19:37Z</updated>

		<summary type="html">&lt;p&gt;Res: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= A bit about me =&lt;br /&gt;
&lt;br /&gt;
My name is Frank Richter, currently studying Computer Sciences at the University of Jena (that's in Germany).&lt;br /&gt;
&lt;br /&gt;
As far as C++ is concerned, I program in it since at least seven years now. In my spare time I also develop for Crystal Space, an open source 3D engine. While I did a lot in the topics of realtime 3D, OpenGL, shaders and such, I also did (and do) 'low-level' things like cross-platform services and, last, but in this context here now certainly not least, matters of ''memory optimization''. &lt;br /&gt;
&lt;br /&gt;
= Current status =&lt;br /&gt;
&lt;br /&gt;
* Upon reading the blog post linked in the idea proposal my first thought was to use a proxy class for operator[]. Below a patch that implements it.&lt;br /&gt;
&lt;br /&gt;
== Proxy class patch ==&lt;br /&gt;
&lt;br /&gt;
This builds and, I believe, works, but has a number of not-so-nice issues:&lt;br /&gt;
* Some places store return values in &amp;lt;tt&amp;gt;t_string&amp;amp;&amp;lt;/tt&amp;gt;. The idea is to change these to &amp;lt;tt&amp;gt;config::proxy_string&amp;lt;/tt&amp;gt;, as that type should ideally behave like &amp;lt;tt&amp;gt;t_string&amp;amp;&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;config::proxy_string&amp;lt;/tt&amp;gt; can cast to both &amp;lt;tt&amp;gt;std::string&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;t_string&amp;lt;/tt&amp;gt;.&lt;br /&gt;
The first is necessary as &amp;lt;tt&amp;gt;t_string&amp;lt;/tt&amp;gt; can cast to it as well; the second is necessary to&lt;br /&gt;
support use of a &amp;lt;tt&amp;gt;config::proxy_string&amp;lt;/tt&amp;gt; where a &amp;lt;tt&amp;gt;const t_string&amp;amp;&amp;lt;/tt&amp;gt; is expected.&lt;br /&gt;
Unfortunately, this introduces an ambiguity in cases where a &amp;lt;tt&amp;gt;config::proxy_string&amp;lt;/tt&amp;gt; is passed to methods that can take either of &amp;lt;tt&amp;gt;std::string&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;t_string&amp;lt;/tt&amp;gt;. The ambiguity was solved in some places by using &amp;lt;tt&amp;gt;.str()&amp;lt;/tt&amp;gt;. It would also go away when &amp;lt;tt&amp;gt;proxy_string operator[]&amp;lt;/tt&amp;gt; is removed.&lt;br /&gt;
* the &amp;lt;tt&amp;gt;variables_set&amp;lt;/tt&amp;gt; class has a member (&amp;lt;tt&amp;gt;get_variable_const()&amp;lt;/tt&amp;gt;) that returns a &amp;lt;tt&amp;gt;t_string&amp;amp;&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;game_state&amp;lt;/tt&amp;gt; descends from this class; it's &amp;lt;tt&amp;gt;get_variable_const()&amp;lt;/tt&amp;gt; implementation supposedly returns a value from a &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;. To ensure the ref is valid, the value as a &amp;lt;tt&amp;gt;t_string&amp;lt;/tt&amp;gt; is stored in a map. This is clearly not ideal.&lt;br /&gt;
&lt;br /&gt;
The patch was submitted to the patch tracker: https://gna.org/patch/index.php?1139&lt;br /&gt;
&lt;br /&gt;
= Next (technically, first) Steps =&lt;br /&gt;
&lt;br /&gt;
* Get rid of &amp;lt;tt&amp;gt;t_string&amp;amp; operator[]&amp;lt;/tt&amp;gt; - could be a proxy class, as above, or like in the initial blog post, a setter function. A way in-between could be to have the proxy class for convenient migration, but mark is a deprecated; instead, promote the usage of the setter. Cases where the proxy class actually introduces ugliness should be fixed manually.&lt;br /&gt;
* Determine the &amp;quot;variation&amp;quot; in strings in configs. E.g. if only very few distinct strings occur during a run of the game string deleting could be ignored and storage one-way (thus simpler). However, while I expect that there is a set of strings which occur often (keywords), there would also be lots of arbitrary strings that need proper deletion lest to introduce a leak.&lt;/div&gt;</summary>
		<author><name>Res</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_res&amp;diff=29068</id>
		<title>SummerOfCodeProposal res</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_res&amp;diff=29068"/>
		<updated>2009-03-22T17:37:22Z</updated>

		<summary type="html">&lt;p&gt;Res: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= A bit about me =&lt;br /&gt;
&lt;br /&gt;
My name is Frank Richter, currently studying Computer Sciences at the University of Jena (that's in Germany).&lt;br /&gt;
&lt;br /&gt;
As far as C++ is concerned, I program in it since at least seven years now. In my spare time I also develop for Crystal Space, an open source 3D engine. While I did a lot in the topics of realtime 3D, OpenGL, shaders and such, I also did (and do) 'low-level' things like cross-platform services and, last, but in this context here now certainly not least, matters of ''memory optimization''. &lt;br /&gt;
&lt;br /&gt;
= Current status =&lt;br /&gt;
&lt;br /&gt;
* Upon reading the blog post linked in the idea proposal my first thought was to use a proxy class for operator[]. Below a patch that implements it.&lt;br /&gt;
&lt;br /&gt;
== Proxy class patch ==&lt;br /&gt;
&lt;br /&gt;
This builds and, I believe, works, but has a number of not-so-nice issues:&lt;br /&gt;
* Some places store return values in &amp;lt;tt&amp;gt;t_string&amp;amp;&amp;lt;/tt&amp;gt;. The idea is to change these to &amp;lt;tt&amp;gt;config::proxy_string&amp;lt;/tt&amp;gt;, as that type should ideally behave like &amp;lt;tt&amp;gt;t_string&amp;amp;&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;config::proxy_string&amp;lt;/tt&amp;gt; can cast to both &amp;lt;tt&amp;gt;std::string&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;t_string&amp;lt;/tt&amp;gt;.&lt;br /&gt;
The first is necessary as &amp;lt;tt&amp;gt;t_string&amp;lt;/tt&amp;gt; can cast to it as well; the second is necessary to&lt;br /&gt;
support use of a &amp;lt;tt&amp;gt;config::proxy_string&amp;lt;/tt&amp;gt; where a &amp;lt;tt&amp;gt;const t_string&amp;amp;&amp;lt;/tt&amp;gt; is expected.&lt;br /&gt;
Unfortunately, this introduces an ambiguity in cases where a &amp;lt;tt&amp;gt;config::proxy_string&amp;lt;/tt&amp;gt; is passed to methods that can take either of &amp;lt;tt&amp;gt;std::string&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;t_string&amp;lt;/tt&amp;gt;. The ambiguity was solved in some places by using &amp;lt;tt&amp;gt;.str()&amp;lt;/tt&amp;gt;. It would also go away when &amp;lt;tt&amp;gt;proxy_string operator[]&amp;lt;/tt&amp;gt; is removed.&lt;br /&gt;
* the &amp;lt;tt&amp;gt;variables_set&amp;lt;/tt&amp;gt; class has a member (&amp;lt;tt&amp;gt;get_variable_const()&amp;lt;/tt&amp;gt;) that returns a &amp;lt;tt&amp;gt;t_string&amp;amp;&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;game_state&amp;lt;/tt&amp;gt; descends from this class; it's &amp;lt;tt&amp;gt;get_variable_const()&amp;lt;/tt&amp;gt; implementation supposedly returns a value from a &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;. To ensure the ref is valid, the value as a &amp;lt;tt&amp;gt;t_string&amp;lt;/tt&amp;gt; is stored in a map. This is clearly not ideal.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Index: src/config.cpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/config.cpp	(revision 33970)&lt;br /&gt;
+++ src/config.cpp	(working copy)&lt;br /&gt;
@@ -293,10 +293,12 @@&lt;br /&gt;
 	delete res;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
+/*&lt;br /&gt;
 t_string&amp;amp; config::operator[](const std::string&amp;amp; key)&lt;br /&gt;
 {&lt;br /&gt;
 	return values[key];&lt;br /&gt;
 }&lt;br /&gt;
+*/&lt;br /&gt;
 &lt;br /&gt;
 const t_string&amp;amp; config::operator[](const std::string&amp;amp; key) const&lt;br /&gt;
 {&lt;br /&gt;
Index: src/font.cpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/font.cpp	(revision 33970)&lt;br /&gt;
+++ src/font.cpp	(working copy)&lt;br /&gt;
@@ -1278,7 +1278,7 @@&lt;br /&gt;
 		known_fonts.insert(font[&amp;quot;name&amp;quot;]);&lt;br /&gt;
 	}&lt;br /&gt;
 &lt;br /&gt;
-	font_order = (*fonts_config)[&amp;quot;order&amp;quot;];&lt;br /&gt;
+	font_order = (*fonts_config)[&amp;quot;order&amp;quot;].t_str();&lt;br /&gt;
 	const std::vector&amp;lt;std::string&amp;gt; font_order = utils::split((*fonts_config)[&amp;quot;order&amp;quot;]);&lt;br /&gt;
 	std::vector&amp;lt;font::subset_descriptor&amp;gt; fontlist;&lt;br /&gt;
 	std::vector&amp;lt;std::string&amp;gt;::const_iterator font;&lt;br /&gt;
Index: src/playsingle_controller.cpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/playsingle_controller.cpp	(revision 33970)&lt;br /&gt;
+++ src/playsingle_controller.cpp	(working copy)&lt;br /&gt;
@@ -281,7 +281,7 @@&lt;br /&gt;
 		// Log before prestart events: they do weird things.&lt;br /&gt;
 		if (first_human_team_ != -1) {&lt;br /&gt;
 			log.start(gamestate_, teams_[first_human_team_], first_human_team_ + 1, units_,&lt;br /&gt;
-					  loading_game_ ? gamestate_.get_variable(&amp;quot;turn_number&amp;quot;) : &amp;quot;&amp;quot;, status_.number_of_turns());&lt;br /&gt;
+					  loading_game_ ? gamestate_.get_variable(&amp;quot;turn_number&amp;quot;).c_str() : &amp;quot;&amp;quot;, status_.number_of_turns());&lt;br /&gt;
 		}&lt;br /&gt;
 &lt;br /&gt;
 		fire_prestart(!loading_game_);&lt;br /&gt;
Index: src/gamestatus.cpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/gamestatus.cpp	(revision 33970)&lt;br /&gt;
+++ src/gamestatus.cpp	(working copy)&lt;br /&gt;
@@ -1166,7 +1166,7 @@&lt;br /&gt;
 	}&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
-t_string&amp;amp; game_state::get_variable(const std::string&amp;amp; key)&lt;br /&gt;
+config::proxy_string game_state::get_variable(const std::string&amp;amp; key)&lt;br /&gt;
 {&lt;br /&gt;
 	return variable_info(key, true, variable_info::TYPE_SCALAR).as_scalar();&lt;br /&gt;
 }&lt;br /&gt;
@@ -1174,8 +1174,9 @@&lt;br /&gt;
 const t_string&amp;amp; game_state::get_variable_const(const std::string&amp;amp; key) const&lt;br /&gt;
 {&lt;br /&gt;
 	variable_info to_get(key, false, variable_info::TYPE_SCALAR);&lt;br /&gt;
-	if(!to_get.is_valid) return temporaries[key];&lt;br /&gt;
-	return to_get.as_scalar();&lt;br /&gt;
+	config::proxy_string val ((!to_get.is_valid) ? temporaries[key] : to_get.as_scalar());&lt;br /&gt;
+	save_t_string[key] = val.t_str();&lt;br /&gt;
+	return save_t_string[key];&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 config&amp;amp; game_state::get_variable_cfg(const std::string&amp;amp; key)&lt;br /&gt;
Index: src/theme.cpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/theme.cpp	(revision 33970)&lt;br /&gt;
+++ src/theme.cpp	(working copy)&lt;br /&gt;
@@ -169,13 +169,13 @@&lt;br /&gt;
 			// follow the inheritance hierarchy and push all the nodes on the stack&lt;br /&gt;
 			std::vector&amp;lt;const config*&amp;gt; parent_stack(1, (*i));&lt;br /&gt;
 			const config* parent;&lt;br /&gt;
-			const t_string* parent_id = &amp;amp;((**i)[&amp;quot;inherits&amp;quot;]);&lt;br /&gt;
-			while((parent = top_cfg.find_child(&amp;quot;resolution&amp;quot;, &amp;quot;id&amp;quot;, (*parent_id))) == NULL) {&lt;br /&gt;
-				parent = top_cfg.find_child(&amp;quot;partialresolution&amp;quot;, &amp;quot;id&amp;quot;, (*parent_id));&lt;br /&gt;
+			t_string parent_id = ((**i)[&amp;quot;inherits&amp;quot;]);&lt;br /&gt;
+			while((parent = top_cfg.find_child(&amp;quot;resolution&amp;quot;, &amp;quot;id&amp;quot;, parent_id)) == NULL) {&lt;br /&gt;
+				parent = top_cfg.find_child(&amp;quot;partialresolution&amp;quot;, &amp;quot;id&amp;quot;, parent_id);&lt;br /&gt;
 				if(parent == NULL)&lt;br /&gt;
-					throw config::error(&amp;quot;[partialresolution] refers to non-existant [resolution] &amp;quot; + (*parent_id).str());&lt;br /&gt;
+					throw config::error(&amp;quot;[partialresolution] refers to non-existant [resolution] &amp;quot; + parent_id.str());&lt;br /&gt;
 				parent_stack.push_back(parent);&lt;br /&gt;
-				parent_id = &amp;amp;((*parent)[&amp;quot;inherits&amp;quot;]);&lt;br /&gt;
+				parent_id = ((*parent)[&amp;quot;inherits&amp;quot;]);&lt;br /&gt;
 			}&lt;br /&gt;
 &lt;br /&gt;
 			// Add the parent resolution and apply all the modifications of its children&lt;br /&gt;
Index: src/variable.hpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/variable.hpp	(revision 33970)&lt;br /&gt;
+++ src/variable.hpp	(working copy)&lt;br /&gt;
@@ -206,7 +206,7 @@&lt;br /&gt;
 	 * Results: after deciding the desired type, these methods can retrieve the result&lt;br /&gt;
 	 * Note: first you should force_valid or check is_valid, otherwise these may fail&lt;br /&gt;
 	 */&lt;br /&gt;
-	t_string&amp;amp; as_scalar();&lt;br /&gt;
+	config::proxy_string as_scalar();&lt;br /&gt;
 	config&amp;amp; as_container();&lt;br /&gt;
 	array_range as_array(); //range may be empty&lt;br /&gt;
 };&lt;br /&gt;
Index: src/game_config.cpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/game_config.cpp	(revision 33970)&lt;br /&gt;
+++ src/game_config.cpp	(working copy)&lt;br /&gt;
@@ -239,7 +239,7 @@&lt;br /&gt;
 				std::string id = (**teamC)[&amp;quot;id&amp;quot;];&lt;br /&gt;
 				std::vector&amp;lt;Uint32&amp;gt; temp = string2rgb((**teamC)[&amp;quot;rgb&amp;quot;]);&lt;br /&gt;
 				team_rgb_range.insert(std::make_pair(id,color_range(temp)));&lt;br /&gt;
-				team_rgb_name[id] = (**teamC)[&amp;quot;name&amp;quot;];&lt;br /&gt;
+				team_rgb_name[id] = (**teamC)[&amp;quot;name&amp;quot;].t_str();&lt;br /&gt;
 				//generate palette of same name;&lt;br /&gt;
 				std::vector&amp;lt;Uint32&amp;gt; tp = palette(team_rgb_range[id]);&lt;br /&gt;
 				if(tp.size()){&lt;br /&gt;
Index: src/config.hpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/config.hpp	(revision 33970)&lt;br /&gt;
+++ src/config.hpp	(working copy)&lt;br /&gt;
@@ -150,6 +150,43 @@&lt;br /&gt;
 	private:&lt;br /&gt;
 		Itor i_;&lt;br /&gt;
 	};&lt;br /&gt;
+	&lt;br /&gt;
+	class proxy_string&lt;br /&gt;
+	{&lt;br /&gt;
+	  config&amp;amp; owner;&lt;br /&gt;
+	  const std::string&amp;amp; key;&lt;br /&gt;
+	  &lt;br /&gt;
+	  t_string&amp;amp; real_str() { return owner.values[key]; }&lt;br /&gt;
+	  const t_string&amp;amp; real_str() const { return owner.values[key]; }&lt;br /&gt;
+	public:&lt;br /&gt;
+	  proxy_string (config&amp;amp; owner, const std::string&amp;amp; key) : owner (owner), key (key) {}&lt;br /&gt;
+	&lt;br /&gt;
+	  proxy_string&amp;amp; operator= (const proxy_string&amp;amp; other)&lt;br /&gt;
+	  { return this-&amp;gt;operator= (other.real_str()); }&lt;br /&gt;
+	    &lt;br /&gt;
+	  proxy_string&amp;amp; operator= (const char* str)&lt;br /&gt;
+	  { real_str() = str; return *this; }&lt;br /&gt;
+	  proxy_string&amp;amp; operator= (const t_string&amp;amp; str)&lt;br /&gt;
+	  { real_str() = str; return *this; }&lt;br /&gt;
+	  proxy_string&amp;amp; operator= (const std::string&amp;amp; str)&lt;br /&gt;
+	  { real_str() = str; return *this; }&lt;br /&gt;
+	  &lt;br /&gt;
+	  proxy_string&amp;amp; operator+= (const std::string&amp;amp; str)&lt;br /&gt;
+	  { real_str() += str; return *this; }&lt;br /&gt;
+	  &lt;br /&gt;
+	  // t_string 'emulation' methods&lt;br /&gt;
+	  bool empty() const { return real_str().empty(); }&lt;br /&gt;
+	  const char* c_str() const { return real_str().c_str(); }&lt;br /&gt;
+	  std::string to_serialized() const { return real_str().to_serialized(); }&lt;br /&gt;
+	  &lt;br /&gt;
+	  const std::string&amp;amp; str() const { return real_str().str(); }&lt;br /&gt;
+	  const t_string&amp;amp; t_str() const { return real_str(); }&lt;br /&gt;
+	  operator std::string () const { return real_str().str(); }&lt;br /&gt;
+	  operator t_string() const { return real_str(); }&lt;br /&gt;
+	  &lt;br /&gt;
+	  inline friend std::ostream&amp;amp; operator&amp;lt;&amp;lt;(std::ostream&amp;amp; os, const proxy_string&amp;amp; str)&lt;br /&gt;
+	  { return os &amp;lt;&amp;lt; str.real_str(); }&lt;br /&gt;
+	};&lt;br /&gt;
 &lt;br /&gt;
 	typedef std::pair&amp;lt;const_attribute_iterator,const_attribute_iterator&amp;gt; const_attr_itors;&lt;br /&gt;
 &lt;br /&gt;
@@ -167,7 +204,10 @@&lt;br /&gt;
 	config&amp;amp; add_child(const std::string&amp;amp; key);&lt;br /&gt;
 	config&amp;amp; add_child(const std::string&amp;amp; key, const config&amp;amp; val);&lt;br /&gt;
 	config&amp;amp; add_child_at(const std::string&amp;amp; key, const config&amp;amp; val, size_t index);&lt;br /&gt;
-	t_string&amp;amp; operator[](const std::string&amp;amp; key);&lt;br /&gt;
+	&lt;br /&gt;
+	//t_string&amp;amp; operator[](const std::string&amp;amp; key);&lt;br /&gt;
+	proxy_string operator[](const std::string&amp;amp; key)&lt;br /&gt;
+	{ return proxy_string (*this, key); }&lt;br /&gt;
 	const t_string&amp;amp; operator[](const std::string&amp;amp; key) const;&lt;br /&gt;
 &lt;br /&gt;
 	const t_string&amp;amp; get_attribute(const std::string&amp;amp; key) const;&lt;br /&gt;
Index: src/game_events.cpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/game_events.cpp	(revision 33970)&lt;br /&gt;
+++ src/game_events.cpp	(working copy)&lt;br /&gt;
@@ -88,10 +88,10 @@&lt;br /&gt;
 	class pump_manager {&lt;br /&gt;
 		public:&lt;br /&gt;
 		pump_manager() :&lt;br /&gt;
-			x1_(state_of_game-&amp;gt;get_variable(&amp;quot;x1&amp;quot;)),&lt;br /&gt;
-			x2_(state_of_game-&amp;gt;get_variable(&amp;quot;x2&amp;quot;)),&lt;br /&gt;
-			y1_(state_of_game-&amp;gt;get_variable(&amp;quot;y1&amp;quot;)),&lt;br /&gt;
-			y2_(state_of_game-&amp;gt;get_variable(&amp;quot;y2&amp;quot;))&lt;br /&gt;
+			x1_(state_of_game-&amp;gt;get_variable(&amp;quot;x1&amp;quot;).str()),&lt;br /&gt;
+			x2_(state_of_game-&amp;gt;get_variable(&amp;quot;x2&amp;quot;).str()),&lt;br /&gt;
+			y1_(state_of_game-&amp;gt;get_variable(&amp;quot;y1&amp;quot;).str()),&lt;br /&gt;
+			y2_(state_of_game-&amp;gt;get_variable(&amp;quot;y2&amp;quot;).str())&lt;br /&gt;
 		{&lt;br /&gt;
 			++instance_count;&lt;br /&gt;
 		}&lt;br /&gt;
@@ -856,7 +856,7 @@&lt;br /&gt;
 &lt;br /&gt;
 	static void store_gold_side(bool store_side, const vconfig&amp;amp; cfg)&lt;br /&gt;
 	{&lt;br /&gt;
-		t_string *gold_store;&lt;br /&gt;
+		config::proxy_string *gold_store = 0;&lt;br /&gt;
 		std::string side = cfg[&amp;quot;side&amp;quot;];&lt;br /&gt;
 		std::string var_name = cfg[&amp;quot;variable&amp;quot;];&lt;br /&gt;
 		if(var_name.empty()) {&lt;br /&gt;
@@ -882,11 +882,12 @@&lt;br /&gt;
 				state_of_game-&amp;gt;get_variable(var_name+&amp;quot;.user_team_name&amp;quot;) = (*teams)[team_index].user_team_name();&lt;br /&gt;
 				state_of_game-&amp;gt;get_variable(var_name+&amp;quot;.colour&amp;quot;) = (*teams)[team_index].map_colour_to();&lt;br /&gt;
 &lt;br /&gt;
-				gold_store = &amp;amp;state_of_game-&amp;gt;get_variable(var_name+&amp;quot;.gold&amp;quot;);&lt;br /&gt;
+				gold_store = new config::proxy_string (state_of_game-&amp;gt;get_variable(var_name+&amp;quot;.gold&amp;quot;));&lt;br /&gt;
 			} else {&lt;br /&gt;
-				gold_store = &amp;amp;state_of_game-&amp;gt;get_variable(var_name);&lt;br /&gt;
+				gold_store = new config::proxy_string (state_of_game-&amp;gt;get_variable(var_name));&lt;br /&gt;
 			}&lt;br /&gt;
 			*gold_store = lexical_cast_default&amp;lt;std::string&amp;gt;((*teams)[team_index].gold(),&amp;quot;&amp;quot;);&lt;br /&gt;
+			delete gold_store;&lt;br /&gt;
 		}&lt;br /&gt;
 	}&lt;br /&gt;
 &lt;br /&gt;
@@ -1158,7 +1159,7 @@&lt;br /&gt;
 		assert(state_of_game != NULL);&lt;br /&gt;
 &lt;br /&gt;
 		const std::string name = cfg[&amp;quot;name&amp;quot;];&lt;br /&gt;
-		t_string&amp;amp; var = state_of_game-&amp;gt;get_variable(name);&lt;br /&gt;
+		config::proxy_string var = state_of_game-&amp;gt;get_variable(name);&lt;br /&gt;
 &lt;br /&gt;
 		const t_string&amp;amp; literal = cfg.get_attribute(&amp;quot;literal&amp;quot;);	// no $var substitution&lt;br /&gt;
 		if(literal.empty() == false) {&lt;br /&gt;
@@ -1191,7 +1192,7 @@&lt;br /&gt;
 &lt;br /&gt;
 		const std::string multiply = cfg[&amp;quot;multiply&amp;quot;];&lt;br /&gt;
 		if(multiply.empty() == false) {&lt;br /&gt;
-			if(isint(var) &amp;amp;&amp;amp; isint(multiply)) {&lt;br /&gt;
+			if(isint(var.str()) &amp;amp;&amp;amp; isint(multiply)) {&lt;br /&gt;
 				var = str_cast( std::atoi(var.c_str()) * std::atoi(multiply.c_str()) );&lt;br /&gt;
 			} else {&lt;br /&gt;
 				var = str_cast( std::atof(var.c_str()) * std::atof(multiply.c_str()) );&lt;br /&gt;
@@ -1204,7 +1205,7 @@&lt;br /&gt;
 				ERR_NG &amp;lt;&amp;lt; &amp;quot;division by zero on variable &amp;quot; &amp;lt;&amp;lt; name &amp;lt;&amp;lt; &amp;quot;\n&amp;quot;;&lt;br /&gt;
 				return;&lt;br /&gt;
 			}&lt;br /&gt;
-			if(isint(var) &amp;amp;&amp;amp; isint(divide)) {&lt;br /&gt;
+			if(isint(var.str()) &amp;amp;&amp;amp; isint(divide)) {&lt;br /&gt;
 				var = str_cast( std::atoi(var.c_str()) / std::atoi(divide.c_str()) );&lt;br /&gt;
 			} else {&lt;br /&gt;
 				var = str_cast( std::atof(var.c_str()) / std::atof(divide.c_str()) );&lt;br /&gt;
@@ -1217,7 +1218,7 @@&lt;br /&gt;
 				ERR_NG &amp;lt;&amp;lt; &amp;quot;division by zero on variable &amp;quot; &amp;lt;&amp;lt; name &amp;lt;&amp;lt; &amp;quot;\n&amp;quot;;&lt;br /&gt;
 				return;&lt;br /&gt;
 			}&lt;br /&gt;
-			if(isint(var) &amp;amp;&amp;amp; isint(modulo)) {&lt;br /&gt;
+			if(isint(var.str()) &amp;amp;&amp;amp; isint(modulo)) {&lt;br /&gt;
 				var = str_cast( std::atoi(var.c_str()) % std::atoi(modulo.c_str()) );&lt;br /&gt;
 			} else {&lt;br /&gt;
 				double value = std::fmod( std::atof(var.c_str()), std::atof(modulo.c_str()) );&lt;br /&gt;
Index: src/gui/dialogs/addon_list.cpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/gui/dialogs/addon_list.cpp	(revision 33970)&lt;br /&gt;
+++ src/gui/dialogs/addon_list.cpp	(working copy)&lt;br /&gt;
@@ -74,10 +74,10 @@&lt;br /&gt;
 		item[&amp;quot;label&amp;quot;] = tmp;&lt;br /&gt;
 		data.insert(std::make_pair(&amp;quot;author&amp;quot;, item));&lt;br /&gt;
 &lt;br /&gt;
-		item[&amp;quot;label&amp;quot;] = (**itor)[&amp;quot;downloads&amp;quot;];&lt;br /&gt;
+		item[&amp;quot;label&amp;quot;] = (**itor)[&amp;quot;downloads&amp;quot;].t_str();&lt;br /&gt;
 		data.insert(std::make_pair(&amp;quot;downloads&amp;quot;, item));&lt;br /&gt;
 &lt;br /&gt;
-		item[&amp;quot;label&amp;quot;] = (**itor)[&amp;quot;size&amp;quot;];&lt;br /&gt;
+		item[&amp;quot;label&amp;quot;] = (**itor)[&amp;quot;size&amp;quot;].t_str();&lt;br /&gt;
 		data.insert(std::make_pair(&amp;quot;size&amp;quot;, item));&lt;br /&gt;
 &lt;br /&gt;
 		list-&amp;gt;add_row(data);&lt;br /&gt;
Index: src/unit_types.cpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/unit_types.cpp	(revision 33970)&lt;br /&gt;
+++ src/unit_types.cpp	(working copy)&lt;br /&gt;
@@ -791,8 +791,8 @@&lt;br /&gt;
         build_created(cfg, mv_types, races, traits);&lt;br /&gt;
     }&lt;br /&gt;
 &lt;br /&gt;
-	type_name_ = cfg_[&amp;quot;name&amp;quot;];&lt;br /&gt;
-	description_ = cfg_[&amp;quot;description&amp;quot;];&lt;br /&gt;
+	type_name_ = cfg_[&amp;quot;name&amp;quot;].t_str();&lt;br /&gt;
+	description_ = cfg_[&amp;quot;description&amp;quot;].t_str();&lt;br /&gt;
 	hitpoints_ = lexical_cast_default&amp;lt;int&amp;gt;(cfg[&amp;quot;hitpoints&amp;quot;], 1);&lt;br /&gt;
 	level_ = lexical_cast_default&amp;lt;int&amp;gt;(cfg[&amp;quot;level&amp;quot;], 0);&lt;br /&gt;
 	movement_ = lexical_cast_default&amp;lt;int&amp;gt;(cfg[&amp;quot;movement&amp;quot;], 1);&lt;br /&gt;
Index: src/gamestatus.hpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/gamestatus.hpp	(revision 33970)&lt;br /&gt;
+++ src/gamestatus.hpp	(working copy)&lt;br /&gt;
@@ -120,7 +120,7 @@&lt;br /&gt;
 &lt;br /&gt;
 	// Variable access&lt;br /&gt;
 &lt;br /&gt;
-	t_string&amp;amp; get_variable(const std::string&amp;amp; varname);&lt;br /&gt;
+	config::proxy_string get_variable(const std::string&amp;amp; varname);&lt;br /&gt;
 	virtual const t_string&amp;amp; get_variable_const(const std::string&amp;amp; varname) const;&lt;br /&gt;
 	config&amp;amp; get_variable_cfg(const std::string&amp;amp; varname);&lt;br /&gt;
 	variable_info::array_range get_variable_cfgs(const std::string&amp;amp; varname);&lt;br /&gt;
@@ -165,6 +165,7 @@&lt;br /&gt;
   rand_rng::simple_rng rng_ ;&lt;br /&gt;
 	config variables;&lt;br /&gt;
 	mutable config temporaries; // lengths of arrays, etc.&lt;br /&gt;
+	mutable string_map save_t_string;&lt;br /&gt;
 	const rand_rng::set_random_generator generator_setter; /**&amp;lt; Make sure that rng is initialized first */&lt;br /&gt;
 	friend struct variable_info;&lt;br /&gt;
 };&lt;br /&gt;
Index: src/variable.cpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/variable.cpp	(revision 33970)&lt;br /&gt;
+++ src/variable.cpp	(working copy)&lt;br /&gt;
@@ -713,7 +713,7 @@&lt;br /&gt;
 	}&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
-t_string&amp;amp; variable_info::as_scalar() {&lt;br /&gt;
+config::proxy_string variable_info::as_scalar() {&lt;br /&gt;
 	assert(is_valid);&lt;br /&gt;
 	return (*vars)[key];&lt;br /&gt;
 }&lt;br /&gt;
Index: src/multiplayer_connect.cpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/multiplayer_connect.cpp	(revision 33970)&lt;br /&gt;
+++ src/multiplayer_connect.cpp	(working copy)&lt;br /&gt;
@@ -1439,8 +1439,8 @@&lt;br /&gt;
 		int side_num = 1;&lt;br /&gt;
 		foreach (config &amp;amp;side, sides)&lt;br /&gt;
 		{&lt;br /&gt;
-			t_string &amp;amp;team_name = side[&amp;quot;team_name&amp;quot;];&lt;br /&gt;
-			t_string &amp;amp;user_team_name = side[&amp;quot;user_team_name&amp;quot;];&lt;br /&gt;
+			config::proxy_string team_name = side[&amp;quot;team_name&amp;quot;];&lt;br /&gt;
+			config::proxy_string user_team_name = side[&amp;quot;user_team_name&amp;quot;];&lt;br /&gt;
 &lt;br /&gt;
 			if(team_name.empty())&lt;br /&gt;
 				team_name = lexical_cast&amp;lt;std::string&amp;gt;(side_num);&lt;br /&gt;
@@ -1465,7 +1465,7 @@&lt;br /&gt;
 		foreach (config &amp;amp;side, sides)&lt;br /&gt;
 		{&lt;br /&gt;
 			const std::string side_num = lexical_cast&amp;lt;std::string&amp;gt;(_side_num);&lt;br /&gt;
-			t_string &amp;amp;team_name = side[&amp;quot;team_name&amp;quot;];&lt;br /&gt;
+			config::proxy_string team_name = side[&amp;quot;team_name&amp;quot;];&lt;br /&gt;
 &lt;br /&gt;
 			if(team_name.empty())&lt;br /&gt;
 				team_name = side_num;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Next (technically, first) Steps =&lt;br /&gt;
&lt;br /&gt;
* Get rid of &amp;lt;tt&amp;gt;t_string&amp;amp; operator[]&amp;lt;/tt&amp;gt; - could be a proxy class, as above, or like in the initial blog post, a setter function. A way in-between could be to have the proxy class for convenient migration, but mark is a deprecated; instead, promote the usage of the setter. Cases where the proxy class actually introduces ugliness should be fixed manually.&lt;br /&gt;
* Determine the &amp;quot;variation&amp;quot; in strings in configs. E.g. if only very few distinct strings occur during a run of the game string deleting could be ignored and storage one-way (thus simpler). However, while I expect that there is a set of strings which occur often (keywords), there would also be lots of arbitrary strings that need proper deletion lest to introduce a leak.&lt;/div&gt;</summary>
		<author><name>Res</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_res&amp;diff=29040</id>
		<title>SummerOfCodeProposal res</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_res&amp;diff=29040"/>
		<updated>2009-03-22T15:25:52Z</updated>

		<summary type="html">&lt;p&gt;Res: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= A bit about me =&lt;br /&gt;
&lt;br /&gt;
My name is Frank Richter, currently studying Computer Sciences at the University of Jena (that's in Germany).&lt;br /&gt;
&lt;br /&gt;
As far as C++ is concerned, I program in it since at least seven years now. In my spare time I also develop for Crystal Space, an open source 3D engine. While I did a lot in the topics of realtime 3D, OpenGL, shaders and such, I also did (and do) 'low-level' things like cross-platform services and, last, but in this context here now certainly not least, matters of ''memory optimization''. &lt;br /&gt;
&lt;br /&gt;
= Current status =&lt;br /&gt;
&lt;br /&gt;
* Upon reading the blog post linked in the idea proposal my first thought was to use a proxy class for operator[]. Below a patch that implements it.&lt;br /&gt;
&lt;br /&gt;
== Proxy class patch ==&lt;br /&gt;
&lt;br /&gt;
This builds and, I believe, works, but has a number of not-so-nice issues:&lt;br /&gt;
* Some places store return values in &amp;lt;tt&amp;gt;t_string&amp;amp;&amp;lt;/tt&amp;gt;. The idea is to change these to &amp;lt;tt&amp;gt;config::proxy_string&amp;lt;/tt&amp;gt;, as that type should ideally behave like &amp;lt;tt&amp;gt;t_string&amp;amp;&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;config::proxy_string&amp;lt;/tt&amp;gt; can cast to both &amp;lt;tt&amp;gt;std::string&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;t_string&amp;lt;/tt&amp;gt;.&lt;br /&gt;
The first is necessary as &amp;lt;tt&amp;gt;t_string&amp;lt;/tt&amp;gt; can cast to it as well; the second is necessary to&lt;br /&gt;
support use of a &amp;lt;tt&amp;gt;config::proxy_string&amp;lt;/tt&amp;gt; where a &amp;lt;tt&amp;gt;const t_string&amp;amp;&amp;lt;/tt&amp;gt; is expected.&lt;br /&gt;
Unfortunately, this introduces an ambiguity in cases where a &amp;lt;tt&amp;gt;config::proxy_string&amp;lt;/tt&amp;gt; is passed to methods that can take either of &amp;lt;tt&amp;gt;std::string&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;t_string&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* the &amp;lt;tt&amp;gt;variables_set&amp;lt;/tt&amp;gt; class has a member (&amp;lt;tt&amp;gt;get_variable_const()&amp;lt;/tt&amp;gt;) that returns a &amp;lt;tt&amp;gt;t_string&amp;amp;&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;game_state&amp;lt;/tt&amp;gt; descends from this class; it's &amp;lt;tt&amp;gt;get_variable_const()&amp;lt;/tt&amp;gt; implementation supposedly returns a value from a &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;. To ensure the ref is valid, the value as a &amp;lt;tt&amp;gt;t_string&amp;lt;/tt&amp;gt; is stored in a map. This is clearly not ideal.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Index: src/config.cpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/config.cpp	(revision 33970)&lt;br /&gt;
+++ src/config.cpp	(working copy)&lt;br /&gt;
@@ -293,10 +293,12 @@&lt;br /&gt;
 	delete res;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
+/*&lt;br /&gt;
 t_string&amp;amp; config::operator[](const std::string&amp;amp; key)&lt;br /&gt;
 {&lt;br /&gt;
 	return values[key];&lt;br /&gt;
 }&lt;br /&gt;
+*/&lt;br /&gt;
 &lt;br /&gt;
 const t_string&amp;amp; config::operator[](const std::string&amp;amp; key) const&lt;br /&gt;
 {&lt;br /&gt;
Index: src/font.cpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/font.cpp	(revision 33970)&lt;br /&gt;
+++ src/font.cpp	(working copy)&lt;br /&gt;
@@ -1278,7 +1278,7 @@&lt;br /&gt;
 		known_fonts.insert(font[&amp;quot;name&amp;quot;]);&lt;br /&gt;
 	}&lt;br /&gt;
 &lt;br /&gt;
-	font_order = (*fonts_config)[&amp;quot;order&amp;quot;];&lt;br /&gt;
+	font_order = (*fonts_config)[&amp;quot;order&amp;quot;].t_str();&lt;br /&gt;
 	const std::vector&amp;lt;std::string&amp;gt; font_order = utils::split((*fonts_config)[&amp;quot;order&amp;quot;]);&lt;br /&gt;
 	std::vector&amp;lt;font::subset_descriptor&amp;gt; fontlist;&lt;br /&gt;
 	std::vector&amp;lt;std::string&amp;gt;::const_iterator font;&lt;br /&gt;
Index: src/playsingle_controller.cpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/playsingle_controller.cpp	(revision 33970)&lt;br /&gt;
+++ src/playsingle_controller.cpp	(working copy)&lt;br /&gt;
@@ -281,7 +281,7 @@&lt;br /&gt;
 		// Log before prestart events: they do weird things.&lt;br /&gt;
 		if (first_human_team_ != -1) {&lt;br /&gt;
 			log.start(gamestate_, teams_[first_human_team_], first_human_team_ + 1, units_,&lt;br /&gt;
-					  loading_game_ ? gamestate_.get_variable(&amp;quot;turn_number&amp;quot;) : &amp;quot;&amp;quot;, status_.number_of_turns());&lt;br /&gt;
+					  loading_game_ ? gamestate_.get_variable(&amp;quot;turn_number&amp;quot;).c_str() : &amp;quot;&amp;quot;, status_.number_of_turns());&lt;br /&gt;
 		}&lt;br /&gt;
 &lt;br /&gt;
 		fire_prestart(!loading_game_);&lt;br /&gt;
Index: src/gamestatus.cpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/gamestatus.cpp	(revision 33970)&lt;br /&gt;
+++ src/gamestatus.cpp	(working copy)&lt;br /&gt;
@@ -1166,7 +1166,7 @@&lt;br /&gt;
 	}&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
-t_string&amp;amp; game_state::get_variable(const std::string&amp;amp; key)&lt;br /&gt;
+config::proxy_string game_state::get_variable(const std::string&amp;amp; key)&lt;br /&gt;
 {&lt;br /&gt;
 	return variable_info(key, true, variable_info::TYPE_SCALAR).as_scalar();&lt;br /&gt;
 }&lt;br /&gt;
@@ -1174,8 +1174,9 @@&lt;br /&gt;
 const t_string&amp;amp; game_state::get_variable_const(const std::string&amp;amp; key) const&lt;br /&gt;
 {&lt;br /&gt;
 	variable_info to_get(key, false, variable_info::TYPE_SCALAR);&lt;br /&gt;
-	if(!to_get.is_valid) return temporaries[key];&lt;br /&gt;
-	return to_get.as_scalar();&lt;br /&gt;
+	config::proxy_string val ((!to_get.is_valid) ? temporaries[key] : to_get.as_scalar());&lt;br /&gt;
+	save_t_string[key] = val.t_str();&lt;br /&gt;
+	return save_t_string[key];&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 config&amp;amp; game_state::get_variable_cfg(const std::string&amp;amp; key)&lt;br /&gt;
Index: src/theme.cpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/theme.cpp	(revision 33970)&lt;br /&gt;
+++ src/theme.cpp	(working copy)&lt;br /&gt;
@@ -169,13 +169,13 @@&lt;br /&gt;
 			// follow the inheritance hierarchy and push all the nodes on the stack&lt;br /&gt;
 			std::vector&amp;lt;const config*&amp;gt; parent_stack(1, (*i));&lt;br /&gt;
 			const config* parent;&lt;br /&gt;
-			const t_string* parent_id = &amp;amp;((**i)[&amp;quot;inherits&amp;quot;]);&lt;br /&gt;
-			while((parent = top_cfg.find_child(&amp;quot;resolution&amp;quot;, &amp;quot;id&amp;quot;, (*parent_id))) == NULL) {&lt;br /&gt;
-				parent = top_cfg.find_child(&amp;quot;partialresolution&amp;quot;, &amp;quot;id&amp;quot;, (*parent_id));&lt;br /&gt;
+			t_string parent_id = ((**i)[&amp;quot;inherits&amp;quot;]);&lt;br /&gt;
+			while((parent = top_cfg.find_child(&amp;quot;resolution&amp;quot;, &amp;quot;id&amp;quot;, parent_id)) == NULL) {&lt;br /&gt;
+				parent = top_cfg.find_child(&amp;quot;partialresolution&amp;quot;, &amp;quot;id&amp;quot;, parent_id);&lt;br /&gt;
 				if(parent == NULL)&lt;br /&gt;
-					throw config::error(&amp;quot;[partialresolution] refers to non-existant [resolution] &amp;quot; + (*parent_id).str());&lt;br /&gt;
+					throw config::error(&amp;quot;[partialresolution] refers to non-existant [resolution] &amp;quot; + parent_id.str());&lt;br /&gt;
 				parent_stack.push_back(parent);&lt;br /&gt;
-				parent_id = &amp;amp;((*parent)[&amp;quot;inherits&amp;quot;]);&lt;br /&gt;
+				parent_id = ((*parent)[&amp;quot;inherits&amp;quot;]);&lt;br /&gt;
 			}&lt;br /&gt;
 &lt;br /&gt;
 			// Add the parent resolution and apply all the modifications of its children&lt;br /&gt;
Index: src/variable.hpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/variable.hpp	(revision 33970)&lt;br /&gt;
+++ src/variable.hpp	(working copy)&lt;br /&gt;
@@ -206,7 +206,7 @@&lt;br /&gt;
 	 * Results: after deciding the desired type, these methods can retrieve the result&lt;br /&gt;
 	 * Note: first you should force_valid or check is_valid, otherwise these may fail&lt;br /&gt;
 	 */&lt;br /&gt;
-	t_string&amp;amp; as_scalar();&lt;br /&gt;
+	config::proxy_string as_scalar();&lt;br /&gt;
 	config&amp;amp; as_container();&lt;br /&gt;
 	array_range as_array(); //range may be empty&lt;br /&gt;
 };&lt;br /&gt;
Index: src/game_config.cpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/game_config.cpp	(revision 33970)&lt;br /&gt;
+++ src/game_config.cpp	(working copy)&lt;br /&gt;
@@ -239,7 +239,7 @@&lt;br /&gt;
 				std::string id = (**teamC)[&amp;quot;id&amp;quot;];&lt;br /&gt;
 				std::vector&amp;lt;Uint32&amp;gt; temp = string2rgb((**teamC)[&amp;quot;rgb&amp;quot;]);&lt;br /&gt;
 				team_rgb_range.insert(std::make_pair(id,color_range(temp)));&lt;br /&gt;
-				team_rgb_name[id] = (**teamC)[&amp;quot;name&amp;quot;];&lt;br /&gt;
+				team_rgb_name[id] = (**teamC)[&amp;quot;name&amp;quot;].t_str();&lt;br /&gt;
 				//generate palette of same name;&lt;br /&gt;
 				std::vector&amp;lt;Uint32&amp;gt; tp = palette(team_rgb_range[id]);&lt;br /&gt;
 				if(tp.size()){&lt;br /&gt;
Index: src/config.hpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/config.hpp	(revision 33970)&lt;br /&gt;
+++ src/config.hpp	(working copy)&lt;br /&gt;
@@ -150,6 +150,43 @@&lt;br /&gt;
 	private:&lt;br /&gt;
 		Itor i_;&lt;br /&gt;
 	};&lt;br /&gt;
+	&lt;br /&gt;
+	class proxy_string&lt;br /&gt;
+	{&lt;br /&gt;
+	  config&amp;amp; owner;&lt;br /&gt;
+	  const std::string&amp;amp; key;&lt;br /&gt;
+	  &lt;br /&gt;
+	  t_string&amp;amp; real_str() { return owner.values[key]; }&lt;br /&gt;
+	  const t_string&amp;amp; real_str() const { return owner.values[key]; }&lt;br /&gt;
+	public:&lt;br /&gt;
+	  proxy_string (config&amp;amp; owner, const std::string&amp;amp; key) : owner (owner), key (key) {}&lt;br /&gt;
+	&lt;br /&gt;
+	  proxy_string&amp;amp; operator= (const proxy_string&amp;amp; other)&lt;br /&gt;
+	  { return this-&amp;gt;operator= (other.real_str()); }&lt;br /&gt;
+	    &lt;br /&gt;
+	  proxy_string&amp;amp; operator= (const char* str)&lt;br /&gt;
+	  { real_str() = str; return *this; }&lt;br /&gt;
+	  proxy_string&amp;amp; operator= (const t_string&amp;amp; str)&lt;br /&gt;
+	  { real_str() = str; return *this; }&lt;br /&gt;
+	  proxy_string&amp;amp; operator= (const std::string&amp;amp; str)&lt;br /&gt;
+	  { real_str() = str; return *this; }&lt;br /&gt;
+	  &lt;br /&gt;
+	  proxy_string&amp;amp; operator+= (const std::string&amp;amp; str)&lt;br /&gt;
+	  { real_str() += str; return *this; }&lt;br /&gt;
+	  &lt;br /&gt;
+	  // t_string 'emulation' methods&lt;br /&gt;
+	  bool empty() const { return real_str().empty(); }&lt;br /&gt;
+	  const char* c_str() const { return real_str().c_str(); }&lt;br /&gt;
+	  std::string to_serialized() const { return real_str().to_serialized(); }&lt;br /&gt;
+	  &lt;br /&gt;
+	  const std::string&amp;amp; str() const { return real_str().str(); }&lt;br /&gt;
+	  const t_string&amp;amp; t_str() const { return real_str(); }&lt;br /&gt;
+	  operator std::string () const { return real_str().str(); }&lt;br /&gt;
+	  operator t_string() const { return real_str(); }&lt;br /&gt;
+	  &lt;br /&gt;
+	  inline friend std::ostream&amp;amp; operator&amp;lt;&amp;lt;(std::ostream&amp;amp; os, const proxy_string&amp;amp; str)&lt;br /&gt;
+	  { return os &amp;lt;&amp;lt; str.real_str(); }&lt;br /&gt;
+	};&lt;br /&gt;
 &lt;br /&gt;
 	typedef std::pair&amp;lt;const_attribute_iterator,const_attribute_iterator&amp;gt; const_attr_itors;&lt;br /&gt;
 &lt;br /&gt;
@@ -167,7 +204,10 @@&lt;br /&gt;
 	config&amp;amp; add_child(const std::string&amp;amp; key);&lt;br /&gt;
 	config&amp;amp; add_child(const std::string&amp;amp; key, const config&amp;amp; val);&lt;br /&gt;
 	config&amp;amp; add_child_at(const std::string&amp;amp; key, const config&amp;amp; val, size_t index);&lt;br /&gt;
-	t_string&amp;amp; operator[](const std::string&amp;amp; key);&lt;br /&gt;
+	&lt;br /&gt;
+	//t_string&amp;amp; operator[](const std::string&amp;amp; key);&lt;br /&gt;
+	proxy_string operator[](const std::string&amp;amp; key)&lt;br /&gt;
+	{ return proxy_string (*this, key); }&lt;br /&gt;
 	const t_string&amp;amp; operator[](const std::string&amp;amp; key) const;&lt;br /&gt;
 &lt;br /&gt;
 	const t_string&amp;amp; get_attribute(const std::string&amp;amp; key) const;&lt;br /&gt;
Index: src/game_events.cpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/game_events.cpp	(revision 33970)&lt;br /&gt;
+++ src/game_events.cpp	(working copy)&lt;br /&gt;
@@ -88,10 +88,10 @@&lt;br /&gt;
 	class pump_manager {&lt;br /&gt;
 		public:&lt;br /&gt;
 		pump_manager() :&lt;br /&gt;
-			x1_(state_of_game-&amp;gt;get_variable(&amp;quot;x1&amp;quot;)),&lt;br /&gt;
-			x2_(state_of_game-&amp;gt;get_variable(&amp;quot;x2&amp;quot;)),&lt;br /&gt;
-			y1_(state_of_game-&amp;gt;get_variable(&amp;quot;y1&amp;quot;)),&lt;br /&gt;
-			y2_(state_of_game-&amp;gt;get_variable(&amp;quot;y2&amp;quot;))&lt;br /&gt;
+			x1_(state_of_game-&amp;gt;get_variable(&amp;quot;x1&amp;quot;).str()),&lt;br /&gt;
+			x2_(state_of_game-&amp;gt;get_variable(&amp;quot;x2&amp;quot;).str()),&lt;br /&gt;
+			y1_(state_of_game-&amp;gt;get_variable(&amp;quot;y1&amp;quot;).str()),&lt;br /&gt;
+			y2_(state_of_game-&amp;gt;get_variable(&amp;quot;y2&amp;quot;).str())&lt;br /&gt;
 		{&lt;br /&gt;
 			++instance_count;&lt;br /&gt;
 		}&lt;br /&gt;
@@ -856,7 +856,7 @@&lt;br /&gt;
 &lt;br /&gt;
 	static void store_gold_side(bool store_side, const vconfig&amp;amp; cfg)&lt;br /&gt;
 	{&lt;br /&gt;
-		t_string *gold_store;&lt;br /&gt;
+		config::proxy_string *gold_store = 0;&lt;br /&gt;
 		std::string side = cfg[&amp;quot;side&amp;quot;];&lt;br /&gt;
 		std::string var_name = cfg[&amp;quot;variable&amp;quot;];&lt;br /&gt;
 		if(var_name.empty()) {&lt;br /&gt;
@@ -882,11 +882,12 @@&lt;br /&gt;
 				state_of_game-&amp;gt;get_variable(var_name+&amp;quot;.user_team_name&amp;quot;) = (*teams)[team_index].user_team_name();&lt;br /&gt;
 				state_of_game-&amp;gt;get_variable(var_name+&amp;quot;.colour&amp;quot;) = (*teams)[team_index].map_colour_to();&lt;br /&gt;
 &lt;br /&gt;
-				gold_store = &amp;amp;state_of_game-&amp;gt;get_variable(var_name+&amp;quot;.gold&amp;quot;);&lt;br /&gt;
+				gold_store = new config::proxy_string (state_of_game-&amp;gt;get_variable(var_name+&amp;quot;.gold&amp;quot;));&lt;br /&gt;
 			} else {&lt;br /&gt;
-				gold_store = &amp;amp;state_of_game-&amp;gt;get_variable(var_name);&lt;br /&gt;
+				gold_store = new config::proxy_string (state_of_game-&amp;gt;get_variable(var_name));&lt;br /&gt;
 			}&lt;br /&gt;
 			*gold_store = lexical_cast_default&amp;lt;std::string&amp;gt;((*teams)[team_index].gold(),&amp;quot;&amp;quot;);&lt;br /&gt;
+			delete gold_store;&lt;br /&gt;
 		}&lt;br /&gt;
 	}&lt;br /&gt;
 &lt;br /&gt;
@@ -1158,7 +1159,7 @@&lt;br /&gt;
 		assert(state_of_game != NULL);&lt;br /&gt;
 &lt;br /&gt;
 		const std::string name = cfg[&amp;quot;name&amp;quot;];&lt;br /&gt;
-		t_string&amp;amp; var = state_of_game-&amp;gt;get_variable(name);&lt;br /&gt;
+		config::proxy_string var = state_of_game-&amp;gt;get_variable(name);&lt;br /&gt;
 &lt;br /&gt;
 		const t_string&amp;amp; literal = cfg.get_attribute(&amp;quot;literal&amp;quot;);	// no $var substitution&lt;br /&gt;
 		if(literal.empty() == false) {&lt;br /&gt;
@@ -1191,7 +1192,7 @@&lt;br /&gt;
 &lt;br /&gt;
 		const std::string multiply = cfg[&amp;quot;multiply&amp;quot;];&lt;br /&gt;
 		if(multiply.empty() == false) {&lt;br /&gt;
-			if(isint(var) &amp;amp;&amp;amp; isint(multiply)) {&lt;br /&gt;
+			if(isint(var.str()) &amp;amp;&amp;amp; isint(multiply)) {&lt;br /&gt;
 				var = str_cast( std::atoi(var.c_str()) * std::atoi(multiply.c_str()) );&lt;br /&gt;
 			} else {&lt;br /&gt;
 				var = str_cast( std::atof(var.c_str()) * std::atof(multiply.c_str()) );&lt;br /&gt;
@@ -1204,7 +1205,7 @@&lt;br /&gt;
 				ERR_NG &amp;lt;&amp;lt; &amp;quot;division by zero on variable &amp;quot; &amp;lt;&amp;lt; name &amp;lt;&amp;lt; &amp;quot;\n&amp;quot;;&lt;br /&gt;
 				return;&lt;br /&gt;
 			}&lt;br /&gt;
-			if(isint(var) &amp;amp;&amp;amp; isint(divide)) {&lt;br /&gt;
+			if(isint(var.str()) &amp;amp;&amp;amp; isint(divide)) {&lt;br /&gt;
 				var = str_cast( std::atoi(var.c_str()) / std::atoi(divide.c_str()) );&lt;br /&gt;
 			} else {&lt;br /&gt;
 				var = str_cast( std::atof(var.c_str()) / std::atof(divide.c_str()) );&lt;br /&gt;
@@ -1217,7 +1218,7 @@&lt;br /&gt;
 				ERR_NG &amp;lt;&amp;lt; &amp;quot;division by zero on variable &amp;quot; &amp;lt;&amp;lt; name &amp;lt;&amp;lt; &amp;quot;\n&amp;quot;;&lt;br /&gt;
 				return;&lt;br /&gt;
 			}&lt;br /&gt;
-			if(isint(var) &amp;amp;&amp;amp; isint(modulo)) {&lt;br /&gt;
+			if(isint(var.str()) &amp;amp;&amp;amp; isint(modulo)) {&lt;br /&gt;
 				var = str_cast( std::atoi(var.c_str()) % std::atoi(modulo.c_str()) );&lt;br /&gt;
 			} else {&lt;br /&gt;
 				double value = std::fmod( std::atof(var.c_str()), std::atof(modulo.c_str()) );&lt;br /&gt;
Index: src/gui/dialogs/addon_list.cpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/gui/dialogs/addon_list.cpp	(revision 33970)&lt;br /&gt;
+++ src/gui/dialogs/addon_list.cpp	(working copy)&lt;br /&gt;
@@ -74,10 +74,10 @@&lt;br /&gt;
 		item[&amp;quot;label&amp;quot;] = tmp;&lt;br /&gt;
 		data.insert(std::make_pair(&amp;quot;author&amp;quot;, item));&lt;br /&gt;
 &lt;br /&gt;
-		item[&amp;quot;label&amp;quot;] = (**itor)[&amp;quot;downloads&amp;quot;];&lt;br /&gt;
+		item[&amp;quot;label&amp;quot;] = (**itor)[&amp;quot;downloads&amp;quot;].t_str();&lt;br /&gt;
 		data.insert(std::make_pair(&amp;quot;downloads&amp;quot;, item));&lt;br /&gt;
 &lt;br /&gt;
-		item[&amp;quot;label&amp;quot;] = (**itor)[&amp;quot;size&amp;quot;];&lt;br /&gt;
+		item[&amp;quot;label&amp;quot;] = (**itor)[&amp;quot;size&amp;quot;].t_str();&lt;br /&gt;
 		data.insert(std::make_pair(&amp;quot;size&amp;quot;, item));&lt;br /&gt;
 &lt;br /&gt;
 		list-&amp;gt;add_row(data);&lt;br /&gt;
Index: src/unit_types.cpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/unit_types.cpp	(revision 33970)&lt;br /&gt;
+++ src/unit_types.cpp	(working copy)&lt;br /&gt;
@@ -791,8 +791,8 @@&lt;br /&gt;
         build_created(cfg, mv_types, races, traits);&lt;br /&gt;
     }&lt;br /&gt;
 &lt;br /&gt;
-	type_name_ = cfg_[&amp;quot;name&amp;quot;];&lt;br /&gt;
-	description_ = cfg_[&amp;quot;description&amp;quot;];&lt;br /&gt;
+	type_name_ = cfg_[&amp;quot;name&amp;quot;].t_str();&lt;br /&gt;
+	description_ = cfg_[&amp;quot;description&amp;quot;].t_str();&lt;br /&gt;
 	hitpoints_ = lexical_cast_default&amp;lt;int&amp;gt;(cfg[&amp;quot;hitpoints&amp;quot;], 1);&lt;br /&gt;
 	level_ = lexical_cast_default&amp;lt;int&amp;gt;(cfg[&amp;quot;level&amp;quot;], 0);&lt;br /&gt;
 	movement_ = lexical_cast_default&amp;lt;int&amp;gt;(cfg[&amp;quot;movement&amp;quot;], 1);&lt;br /&gt;
Index: src/gamestatus.hpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/gamestatus.hpp	(revision 33970)&lt;br /&gt;
+++ src/gamestatus.hpp	(working copy)&lt;br /&gt;
@@ -120,7 +120,7 @@&lt;br /&gt;
 &lt;br /&gt;
 	// Variable access&lt;br /&gt;
 &lt;br /&gt;
-	t_string&amp;amp; get_variable(const std::string&amp;amp; varname);&lt;br /&gt;
+	config::proxy_string get_variable(const std::string&amp;amp; varname);&lt;br /&gt;
 	virtual const t_string&amp;amp; get_variable_const(const std::string&amp;amp; varname) const;&lt;br /&gt;
 	config&amp;amp; get_variable_cfg(const std::string&amp;amp; varname);&lt;br /&gt;
 	variable_info::array_range get_variable_cfgs(const std::string&amp;amp; varname);&lt;br /&gt;
@@ -165,6 +165,7 @@&lt;br /&gt;
   rand_rng::simple_rng rng_ ;&lt;br /&gt;
 	config variables;&lt;br /&gt;
 	mutable config temporaries; // lengths of arrays, etc.&lt;br /&gt;
+	mutable string_map save_t_string;&lt;br /&gt;
 	const rand_rng::set_random_generator generator_setter; /**&amp;lt; Make sure that rng is initialized first */&lt;br /&gt;
 	friend struct variable_info;&lt;br /&gt;
 };&lt;br /&gt;
Index: src/variable.cpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/variable.cpp	(revision 33970)&lt;br /&gt;
+++ src/variable.cpp	(working copy)&lt;br /&gt;
@@ -713,7 +713,7 @@&lt;br /&gt;
 	}&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
-t_string&amp;amp; variable_info::as_scalar() {&lt;br /&gt;
+config::proxy_string variable_info::as_scalar() {&lt;br /&gt;
 	assert(is_valid);&lt;br /&gt;
 	return (*vars)[key];&lt;br /&gt;
 }&lt;br /&gt;
Index: src/multiplayer_connect.cpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/multiplayer_connect.cpp	(revision 33970)&lt;br /&gt;
+++ src/multiplayer_connect.cpp	(working copy)&lt;br /&gt;
@@ -1439,8 +1439,8 @@&lt;br /&gt;
 		int side_num = 1;&lt;br /&gt;
 		foreach (config &amp;amp;side, sides)&lt;br /&gt;
 		{&lt;br /&gt;
-			t_string &amp;amp;team_name = side[&amp;quot;team_name&amp;quot;];&lt;br /&gt;
-			t_string &amp;amp;user_team_name = side[&amp;quot;user_team_name&amp;quot;];&lt;br /&gt;
+			config::proxy_string team_name = side[&amp;quot;team_name&amp;quot;];&lt;br /&gt;
+			config::proxy_string user_team_name = side[&amp;quot;user_team_name&amp;quot;];&lt;br /&gt;
 &lt;br /&gt;
 			if(team_name.empty())&lt;br /&gt;
 				team_name = lexical_cast&amp;lt;std::string&amp;gt;(side_num);&lt;br /&gt;
@@ -1465,7 +1465,7 @@&lt;br /&gt;
 		foreach (config &amp;amp;side, sides)&lt;br /&gt;
 		{&lt;br /&gt;
 			const std::string side_num = lexical_cast&amp;lt;std::string&amp;gt;(_side_num);&lt;br /&gt;
-			t_string &amp;amp;team_name = side[&amp;quot;team_name&amp;quot;];&lt;br /&gt;
+			config::proxy_string team_name = side[&amp;quot;team_name&amp;quot;];&lt;br /&gt;
 &lt;br /&gt;
 			if(team_name.empty())&lt;br /&gt;
 				team_name = side_num;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Next (technically, first) Steps =&lt;br /&gt;
&lt;br /&gt;
* Get rid of &amp;lt;tt&amp;gt;t_string&amp;amp; operator[]&amp;lt;/tt&amp;gt; - could be a proxy class, as above, or like in the initial blog post, a setter function. A way in-between could be to have the proxy class for convenient migration, but mark is a deprecated; instead, promote the usage of the setter. Cases where the proxy class actually introduces ugliness should be fixed manually.&lt;br /&gt;
* Determine the &amp;quot;variation&amp;quot; in strings in configs. E.g. if only very few distinct strings occur during a run of the game string deleting could be ignored and storage one-way (thus simpler). However, while I expect that there is a set of strings which occur often (keywords), there would also be lots of arbitrary strings that need proper deletion lest to introduce a leak.&lt;/div&gt;</summary>
		<author><name>Res</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_res&amp;diff=29034</id>
		<title>SummerOfCodeProposal res</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_res&amp;diff=29034"/>
		<updated>2009-03-22T15:18:45Z</updated>

		<summary type="html">&lt;p&gt;Res: /* Current status */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= A bit about me =&lt;br /&gt;
&lt;br /&gt;
My name is Frank Richter, currently studying Computer Sciences at the University of Jena (that's in Germany).&lt;br /&gt;
&lt;br /&gt;
As far as C++ is concerned, I program in it since at least seven years now. In my spare time I also develop for Crystal Space, an open source 3D engine. While I did a lot in the topics of realtime 3D, OpenGL, shaders and such, I also did (and do) 'low-level' things like cross-platform services and, last, but in this context here now certainly not least, matters of ''memory optimization''. &lt;br /&gt;
&lt;br /&gt;
= Current status =&lt;br /&gt;
&lt;br /&gt;
* Upon reading the blog post linked in the idea proposal my first thought was to use a proxy class for operator[]. Below a patch that implements it.&lt;br /&gt;
&lt;br /&gt;
== Proxy class patch ==&lt;br /&gt;
&lt;br /&gt;
This builds and, I believe, works, but has a number of not-so-nice issues:&lt;br /&gt;
* Some places store return values in &amp;lt;tt&amp;gt;t_string&amp;amp;&amp;lt;/tt&amp;gt;. The idea is to change these to &amp;lt;tt&amp;gt;config::proxy_string&amp;lt;/tt&amp;gt;, as that type should ideally behave like &amp;lt;tt&amp;gt;t_string&amp;amp;&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;config::proxy_string&amp;lt;/tt&amp;gt; can cast to both &amp;lt;tt&amp;gt;std::string&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;t_string&amp;lt;/tt&amp;gt;.&lt;br /&gt;
The first is necessary as &amp;lt;tt&amp;gt;t_string&amp;lt;/tt&amp;gt; can cast to it as well; the second is necessary to&lt;br /&gt;
support use of a &amp;lt;tt&amp;gt;config::proxy_string&amp;lt;/tt&amp;gt; where a &amp;lt;tt&amp;gt;const t_string&amp;amp;&amp;lt;/tt&amp;gt; is expected.&lt;br /&gt;
Unfortunately, this introduces an ambiguity in cases where a &amp;lt;tt&amp;gt;config::proxy_string&amp;lt;/tt&amp;gt; is passed to methods that can take either of &amp;lt;tt&amp;gt;std::string&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;t_string&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* the &amp;lt;tt&amp;gt;variables_set&amp;lt;/tt&amp;gt; class has a member (&amp;lt;tt&amp;gt;get_variable_const()&amp;lt;/tt&amp;gt;) that returns a &amp;lt;tt&amp;gt;t_string&amp;amp;&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;game_state&amp;lt;/tt&amp;gt; descends from this class; it's &amp;lt;tt&amp;gt;get_variable_const()&amp;lt;/tt&amp;gt; implementation supposedly returns a value from a &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;. To ensure the ref is valid, the value as a &amp;lt;tt&amp;gt;t_string&amp;lt;/tt&amp;gt; is stored in a map. This is clearly not ideal.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Index: src/config.cpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/config.cpp	(revision 33970)&lt;br /&gt;
+++ src/config.cpp	(working copy)&lt;br /&gt;
@@ -293,10 +293,12 @@&lt;br /&gt;
 	delete res;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
+/*&lt;br /&gt;
 t_string&amp;amp; config::operator[](const std::string&amp;amp; key)&lt;br /&gt;
 {&lt;br /&gt;
 	return values[key];&lt;br /&gt;
 }&lt;br /&gt;
+*/&lt;br /&gt;
 &lt;br /&gt;
 const t_string&amp;amp; config::operator[](const std::string&amp;amp; key) const&lt;br /&gt;
 {&lt;br /&gt;
Index: src/font.cpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/font.cpp	(revision 33970)&lt;br /&gt;
+++ src/font.cpp	(working copy)&lt;br /&gt;
@@ -1278,7 +1278,7 @@&lt;br /&gt;
 		known_fonts.insert(font[&amp;quot;name&amp;quot;]);&lt;br /&gt;
 	}&lt;br /&gt;
 &lt;br /&gt;
-	font_order = (*fonts_config)[&amp;quot;order&amp;quot;];&lt;br /&gt;
+	font_order = (*fonts_config)[&amp;quot;order&amp;quot;].t_str();&lt;br /&gt;
 	const std::vector&amp;lt;std::string&amp;gt; font_order = utils::split((*fonts_config)[&amp;quot;order&amp;quot;]);&lt;br /&gt;
 	std::vector&amp;lt;font::subset_descriptor&amp;gt; fontlist;&lt;br /&gt;
 	std::vector&amp;lt;std::string&amp;gt;::const_iterator font;&lt;br /&gt;
Index: src/playsingle_controller.cpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/playsingle_controller.cpp	(revision 33970)&lt;br /&gt;
+++ src/playsingle_controller.cpp	(working copy)&lt;br /&gt;
@@ -281,7 +281,7 @@&lt;br /&gt;
 		// Log before prestart events: they do weird things.&lt;br /&gt;
 		if (first_human_team_ != -1) {&lt;br /&gt;
 			log.start(gamestate_, teams_[first_human_team_], first_human_team_ + 1, units_,&lt;br /&gt;
-					  loading_game_ ? gamestate_.get_variable(&amp;quot;turn_number&amp;quot;) : &amp;quot;&amp;quot;, status_.number_of_turns());&lt;br /&gt;
+					  loading_game_ ? gamestate_.get_variable(&amp;quot;turn_number&amp;quot;).c_str() : &amp;quot;&amp;quot;, status_.number_of_turns());&lt;br /&gt;
 		}&lt;br /&gt;
 &lt;br /&gt;
 		fire_prestart(!loading_game_);&lt;br /&gt;
Index: src/gamestatus.cpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/gamestatus.cpp	(revision 33970)&lt;br /&gt;
+++ src/gamestatus.cpp	(working copy)&lt;br /&gt;
@@ -1166,7 +1166,7 @@&lt;br /&gt;
 	}&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
-t_string&amp;amp; game_state::get_variable(const std::string&amp;amp; key)&lt;br /&gt;
+config::proxy_string game_state::get_variable(const std::string&amp;amp; key)&lt;br /&gt;
 {&lt;br /&gt;
 	return variable_info(key, true, variable_info::TYPE_SCALAR).as_scalar();&lt;br /&gt;
 }&lt;br /&gt;
@@ -1174,8 +1174,9 @@&lt;br /&gt;
 const t_string&amp;amp; game_state::get_variable_const(const std::string&amp;amp; key) const&lt;br /&gt;
 {&lt;br /&gt;
 	variable_info to_get(key, false, variable_info::TYPE_SCALAR);&lt;br /&gt;
-	if(!to_get.is_valid) return temporaries[key];&lt;br /&gt;
-	return to_get.as_scalar();&lt;br /&gt;
+	config::proxy_string val ((!to_get.is_valid) ? temporaries[key] : to_get.as_scalar());&lt;br /&gt;
+	save_t_string[key] = val.t_str();&lt;br /&gt;
+	return save_t_string[key];&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 config&amp;amp; game_state::get_variable_cfg(const std::string&amp;amp; key)&lt;br /&gt;
Index: src/theme.cpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/theme.cpp	(revision 33970)&lt;br /&gt;
+++ src/theme.cpp	(working copy)&lt;br /&gt;
@@ -169,13 +169,13 @@&lt;br /&gt;
 			// follow the inheritance hierarchy and push all the nodes on the stack&lt;br /&gt;
 			std::vector&amp;lt;const config*&amp;gt; parent_stack(1, (*i));&lt;br /&gt;
 			const config* parent;&lt;br /&gt;
-			const t_string* parent_id = &amp;amp;((**i)[&amp;quot;inherits&amp;quot;]);&lt;br /&gt;
-			while((parent = top_cfg.find_child(&amp;quot;resolution&amp;quot;, &amp;quot;id&amp;quot;, (*parent_id))) == NULL) {&lt;br /&gt;
-				parent = top_cfg.find_child(&amp;quot;partialresolution&amp;quot;, &amp;quot;id&amp;quot;, (*parent_id));&lt;br /&gt;
+			t_string parent_id = ((**i)[&amp;quot;inherits&amp;quot;]);&lt;br /&gt;
+			while((parent = top_cfg.find_child(&amp;quot;resolution&amp;quot;, &amp;quot;id&amp;quot;, parent_id)) == NULL) {&lt;br /&gt;
+				parent = top_cfg.find_child(&amp;quot;partialresolution&amp;quot;, &amp;quot;id&amp;quot;, parent_id);&lt;br /&gt;
 				if(parent == NULL)&lt;br /&gt;
-					throw config::error(&amp;quot;[partialresolution] refers to non-existant [resolution] &amp;quot; + (*parent_id).str());&lt;br /&gt;
+					throw config::error(&amp;quot;[partialresolution] refers to non-existant [resolution] &amp;quot; + parent_id.str());&lt;br /&gt;
 				parent_stack.push_back(parent);&lt;br /&gt;
-				parent_id = &amp;amp;((*parent)[&amp;quot;inherits&amp;quot;]);&lt;br /&gt;
+				parent_id = ((*parent)[&amp;quot;inherits&amp;quot;]);&lt;br /&gt;
 			}&lt;br /&gt;
 &lt;br /&gt;
 			// Add the parent resolution and apply all the modifications of its children&lt;br /&gt;
Index: src/variable.hpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/variable.hpp	(revision 33970)&lt;br /&gt;
+++ src/variable.hpp	(working copy)&lt;br /&gt;
@@ -206,7 +206,7 @@&lt;br /&gt;
 	 * Results: after deciding the desired type, these methods can retrieve the result&lt;br /&gt;
 	 * Note: first you should force_valid or check is_valid, otherwise these may fail&lt;br /&gt;
 	 */&lt;br /&gt;
-	t_string&amp;amp; as_scalar();&lt;br /&gt;
+	config::proxy_string as_scalar();&lt;br /&gt;
 	config&amp;amp; as_container();&lt;br /&gt;
 	array_range as_array(); //range may be empty&lt;br /&gt;
 };&lt;br /&gt;
Index: src/game_config.cpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/game_config.cpp	(revision 33970)&lt;br /&gt;
+++ src/game_config.cpp	(working copy)&lt;br /&gt;
@@ -239,7 +239,7 @@&lt;br /&gt;
 				std::string id = (**teamC)[&amp;quot;id&amp;quot;];&lt;br /&gt;
 				std::vector&amp;lt;Uint32&amp;gt; temp = string2rgb((**teamC)[&amp;quot;rgb&amp;quot;]);&lt;br /&gt;
 				team_rgb_range.insert(std::make_pair(id,color_range(temp)));&lt;br /&gt;
-				team_rgb_name[id] = (**teamC)[&amp;quot;name&amp;quot;];&lt;br /&gt;
+				team_rgb_name[id] = (**teamC)[&amp;quot;name&amp;quot;].t_str();&lt;br /&gt;
 				//generate palette of same name;&lt;br /&gt;
 				std::vector&amp;lt;Uint32&amp;gt; tp = palette(team_rgb_range[id]);&lt;br /&gt;
 				if(tp.size()){&lt;br /&gt;
Index: src/config.hpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/config.hpp	(revision 33970)&lt;br /&gt;
+++ src/config.hpp	(working copy)&lt;br /&gt;
@@ -150,6 +150,43 @@&lt;br /&gt;
 	private:&lt;br /&gt;
 		Itor i_;&lt;br /&gt;
 	};&lt;br /&gt;
+	&lt;br /&gt;
+	class proxy_string&lt;br /&gt;
+	{&lt;br /&gt;
+	  config&amp;amp; owner;&lt;br /&gt;
+	  const std::string&amp;amp; key;&lt;br /&gt;
+	  &lt;br /&gt;
+	  t_string&amp;amp; real_str() { return owner.values[key]; }&lt;br /&gt;
+	  const t_string&amp;amp; real_str() const { return owner.values[key]; }&lt;br /&gt;
+	public:&lt;br /&gt;
+	  proxy_string (config&amp;amp; owner, const std::string&amp;amp; key) : owner (owner), key (key) {}&lt;br /&gt;
+	&lt;br /&gt;
+	  proxy_string&amp;amp; operator= (const proxy_string&amp;amp; other)&lt;br /&gt;
+	  { return this-&amp;gt;operator= (other.real_str()); }&lt;br /&gt;
+	    &lt;br /&gt;
+	  proxy_string&amp;amp; operator= (const char* str)&lt;br /&gt;
+	  { real_str() = str; return *this; }&lt;br /&gt;
+	  proxy_string&amp;amp; operator= (const t_string&amp;amp; str)&lt;br /&gt;
+	  { real_str() = str; return *this; }&lt;br /&gt;
+	  proxy_string&amp;amp; operator= (const std::string&amp;amp; str)&lt;br /&gt;
+	  { real_str() = str; return *this; }&lt;br /&gt;
+	  &lt;br /&gt;
+	  proxy_string&amp;amp; operator+= (const std::string&amp;amp; str)&lt;br /&gt;
+	  { real_str() += str; return *this; }&lt;br /&gt;
+	  &lt;br /&gt;
+	  // t_string 'emulation' methods&lt;br /&gt;
+	  bool empty() const { return real_str().empty(); }&lt;br /&gt;
+	  const char* c_str() const { return real_str().c_str(); }&lt;br /&gt;
+	  std::string to_serialized() const { return real_str().to_serialized(); }&lt;br /&gt;
+	  &lt;br /&gt;
+	  const std::string&amp;amp; str() const { return real_str().str(); }&lt;br /&gt;
+	  const t_string&amp;amp; t_str() const { return real_str(); }&lt;br /&gt;
+	  operator std::string () const { return real_str().str(); }&lt;br /&gt;
+	  operator t_string() const { return real_str(); }&lt;br /&gt;
+	  &lt;br /&gt;
+	  inline friend std::ostream&amp;amp; operator&amp;lt;&amp;lt;(std::ostream&amp;amp; os, const proxy_string&amp;amp; str)&lt;br /&gt;
+	  { return os &amp;lt;&amp;lt; str.real_str(); }&lt;br /&gt;
+	};&lt;br /&gt;
 &lt;br /&gt;
 	typedef std::pair&amp;lt;const_attribute_iterator,const_attribute_iterator&amp;gt; const_attr_itors;&lt;br /&gt;
 &lt;br /&gt;
@@ -167,7 +204,10 @@&lt;br /&gt;
 	config&amp;amp; add_child(const std::string&amp;amp; key);&lt;br /&gt;
 	config&amp;amp; add_child(const std::string&amp;amp; key, const config&amp;amp; val);&lt;br /&gt;
 	config&amp;amp; add_child_at(const std::string&amp;amp; key, const config&amp;amp; val, size_t index);&lt;br /&gt;
-	t_string&amp;amp; operator[](const std::string&amp;amp; key);&lt;br /&gt;
+	&lt;br /&gt;
+	//t_string&amp;amp; operator[](const std::string&amp;amp; key);&lt;br /&gt;
+	proxy_string operator[](const std::string&amp;amp; key)&lt;br /&gt;
+	{ return proxy_string (*this, key); }&lt;br /&gt;
 	const t_string&amp;amp; operator[](const std::string&amp;amp; key) const;&lt;br /&gt;
 &lt;br /&gt;
 	const t_string&amp;amp; get_attribute(const std::string&amp;amp; key) const;&lt;br /&gt;
Index: src/game_events.cpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/game_events.cpp	(revision 33970)&lt;br /&gt;
+++ src/game_events.cpp	(working copy)&lt;br /&gt;
@@ -88,10 +88,10 @@&lt;br /&gt;
 	class pump_manager {&lt;br /&gt;
 		public:&lt;br /&gt;
 		pump_manager() :&lt;br /&gt;
-			x1_(state_of_game-&amp;gt;get_variable(&amp;quot;x1&amp;quot;)),&lt;br /&gt;
-			x2_(state_of_game-&amp;gt;get_variable(&amp;quot;x2&amp;quot;)),&lt;br /&gt;
-			y1_(state_of_game-&amp;gt;get_variable(&amp;quot;y1&amp;quot;)),&lt;br /&gt;
-			y2_(state_of_game-&amp;gt;get_variable(&amp;quot;y2&amp;quot;))&lt;br /&gt;
+			x1_(state_of_game-&amp;gt;get_variable(&amp;quot;x1&amp;quot;).str()),&lt;br /&gt;
+			x2_(state_of_game-&amp;gt;get_variable(&amp;quot;x2&amp;quot;).str()),&lt;br /&gt;
+			y1_(state_of_game-&amp;gt;get_variable(&amp;quot;y1&amp;quot;).str()),&lt;br /&gt;
+			y2_(state_of_game-&amp;gt;get_variable(&amp;quot;y2&amp;quot;).str())&lt;br /&gt;
 		{&lt;br /&gt;
 			++instance_count;&lt;br /&gt;
 		}&lt;br /&gt;
@@ -856,7 +856,7 @@&lt;br /&gt;
 &lt;br /&gt;
 	static void store_gold_side(bool store_side, const vconfig&amp;amp; cfg)&lt;br /&gt;
 	{&lt;br /&gt;
-		t_string *gold_store;&lt;br /&gt;
+		config::proxy_string *gold_store = 0;&lt;br /&gt;
 		std::string side = cfg[&amp;quot;side&amp;quot;];&lt;br /&gt;
 		std::string var_name = cfg[&amp;quot;variable&amp;quot;];&lt;br /&gt;
 		if(var_name.empty()) {&lt;br /&gt;
@@ -882,11 +882,12 @@&lt;br /&gt;
 				state_of_game-&amp;gt;get_variable(var_name+&amp;quot;.user_team_name&amp;quot;) = (*teams)[team_index].user_team_name();&lt;br /&gt;
 				state_of_game-&amp;gt;get_variable(var_name+&amp;quot;.colour&amp;quot;) = (*teams)[team_index].map_colour_to();&lt;br /&gt;
 &lt;br /&gt;
-				gold_store = &amp;amp;state_of_game-&amp;gt;get_variable(var_name+&amp;quot;.gold&amp;quot;);&lt;br /&gt;
+				gold_store = new config::proxy_string (state_of_game-&amp;gt;get_variable(var_name+&amp;quot;.gold&amp;quot;));&lt;br /&gt;
 			} else {&lt;br /&gt;
-				gold_store = &amp;amp;state_of_game-&amp;gt;get_variable(var_name);&lt;br /&gt;
+				gold_store = new config::proxy_string (state_of_game-&amp;gt;get_variable(var_name));&lt;br /&gt;
 			}&lt;br /&gt;
 			*gold_store = lexical_cast_default&amp;lt;std::string&amp;gt;((*teams)[team_index].gold(),&amp;quot;&amp;quot;);&lt;br /&gt;
+			delete gold_store;&lt;br /&gt;
 		}&lt;br /&gt;
 	}&lt;br /&gt;
 &lt;br /&gt;
@@ -1158,7 +1159,7 @@&lt;br /&gt;
 		assert(state_of_game != NULL);&lt;br /&gt;
 &lt;br /&gt;
 		const std::string name = cfg[&amp;quot;name&amp;quot;];&lt;br /&gt;
-		t_string&amp;amp; var = state_of_game-&amp;gt;get_variable(name);&lt;br /&gt;
+		config::proxy_string var = state_of_game-&amp;gt;get_variable(name);&lt;br /&gt;
 &lt;br /&gt;
 		const t_string&amp;amp; literal = cfg.get_attribute(&amp;quot;literal&amp;quot;);	// no $var substitution&lt;br /&gt;
 		if(literal.empty() == false) {&lt;br /&gt;
@@ -1191,7 +1192,7 @@&lt;br /&gt;
 &lt;br /&gt;
 		const std::string multiply = cfg[&amp;quot;multiply&amp;quot;];&lt;br /&gt;
 		if(multiply.empty() == false) {&lt;br /&gt;
-			if(isint(var) &amp;amp;&amp;amp; isint(multiply)) {&lt;br /&gt;
+			if(isint(var.str()) &amp;amp;&amp;amp; isint(multiply)) {&lt;br /&gt;
 				var = str_cast( std::atoi(var.c_str()) * std::atoi(multiply.c_str()) );&lt;br /&gt;
 			} else {&lt;br /&gt;
 				var = str_cast( std::atof(var.c_str()) * std::atof(multiply.c_str()) );&lt;br /&gt;
@@ -1204,7 +1205,7 @@&lt;br /&gt;
 				ERR_NG &amp;lt;&amp;lt; &amp;quot;division by zero on variable &amp;quot; &amp;lt;&amp;lt; name &amp;lt;&amp;lt; &amp;quot;\n&amp;quot;;&lt;br /&gt;
 				return;&lt;br /&gt;
 			}&lt;br /&gt;
-			if(isint(var) &amp;amp;&amp;amp; isint(divide)) {&lt;br /&gt;
+			if(isint(var.str()) &amp;amp;&amp;amp; isint(divide)) {&lt;br /&gt;
 				var = str_cast( std::atoi(var.c_str()) / std::atoi(divide.c_str()) );&lt;br /&gt;
 			} else {&lt;br /&gt;
 				var = str_cast( std::atof(var.c_str()) / std::atof(divide.c_str()) );&lt;br /&gt;
@@ -1217,7 +1218,7 @@&lt;br /&gt;
 				ERR_NG &amp;lt;&amp;lt; &amp;quot;division by zero on variable &amp;quot; &amp;lt;&amp;lt; name &amp;lt;&amp;lt; &amp;quot;\n&amp;quot;;&lt;br /&gt;
 				return;&lt;br /&gt;
 			}&lt;br /&gt;
-			if(isint(var) &amp;amp;&amp;amp; isint(modulo)) {&lt;br /&gt;
+			if(isint(var.str()) &amp;amp;&amp;amp; isint(modulo)) {&lt;br /&gt;
 				var = str_cast( std::atoi(var.c_str()) % std::atoi(modulo.c_str()) );&lt;br /&gt;
 			} else {&lt;br /&gt;
 				double value = std::fmod( std::atof(var.c_str()), std::atof(modulo.c_str()) );&lt;br /&gt;
Index: src/gui/dialogs/addon_list.cpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/gui/dialogs/addon_list.cpp	(revision 33970)&lt;br /&gt;
+++ src/gui/dialogs/addon_list.cpp	(working copy)&lt;br /&gt;
@@ -74,10 +74,10 @@&lt;br /&gt;
 		item[&amp;quot;label&amp;quot;] = tmp;&lt;br /&gt;
 		data.insert(std::make_pair(&amp;quot;author&amp;quot;, item));&lt;br /&gt;
 &lt;br /&gt;
-		item[&amp;quot;label&amp;quot;] = (**itor)[&amp;quot;downloads&amp;quot;];&lt;br /&gt;
+		item[&amp;quot;label&amp;quot;] = (**itor)[&amp;quot;downloads&amp;quot;].t_str();&lt;br /&gt;
 		data.insert(std::make_pair(&amp;quot;downloads&amp;quot;, item));&lt;br /&gt;
 &lt;br /&gt;
-		item[&amp;quot;label&amp;quot;] = (**itor)[&amp;quot;size&amp;quot;];&lt;br /&gt;
+		item[&amp;quot;label&amp;quot;] = (**itor)[&amp;quot;size&amp;quot;].t_str();&lt;br /&gt;
 		data.insert(std::make_pair(&amp;quot;size&amp;quot;, item));&lt;br /&gt;
 &lt;br /&gt;
 		list-&amp;gt;add_row(data);&lt;br /&gt;
Index: src/unit_types.cpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/unit_types.cpp	(revision 33970)&lt;br /&gt;
+++ src/unit_types.cpp	(working copy)&lt;br /&gt;
@@ -791,8 +791,8 @@&lt;br /&gt;
         build_created(cfg, mv_types, races, traits);&lt;br /&gt;
     }&lt;br /&gt;
 &lt;br /&gt;
-	type_name_ = cfg_[&amp;quot;name&amp;quot;];&lt;br /&gt;
-	description_ = cfg_[&amp;quot;description&amp;quot;];&lt;br /&gt;
+	type_name_ = cfg_[&amp;quot;name&amp;quot;].t_str();&lt;br /&gt;
+	description_ = cfg_[&amp;quot;description&amp;quot;].t_str();&lt;br /&gt;
 	hitpoints_ = lexical_cast_default&amp;lt;int&amp;gt;(cfg[&amp;quot;hitpoints&amp;quot;], 1);&lt;br /&gt;
 	level_ = lexical_cast_default&amp;lt;int&amp;gt;(cfg[&amp;quot;level&amp;quot;], 0);&lt;br /&gt;
 	movement_ = lexical_cast_default&amp;lt;int&amp;gt;(cfg[&amp;quot;movement&amp;quot;], 1);&lt;br /&gt;
Index: src/gamestatus.hpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/gamestatus.hpp	(revision 33970)&lt;br /&gt;
+++ src/gamestatus.hpp	(working copy)&lt;br /&gt;
@@ -120,7 +120,7 @@&lt;br /&gt;
 &lt;br /&gt;
 	// Variable access&lt;br /&gt;
 &lt;br /&gt;
-	t_string&amp;amp; get_variable(const std::string&amp;amp; varname);&lt;br /&gt;
+	config::proxy_string get_variable(const std::string&amp;amp; varname);&lt;br /&gt;
 	virtual const t_string&amp;amp; get_variable_const(const std::string&amp;amp; varname) const;&lt;br /&gt;
 	config&amp;amp; get_variable_cfg(const std::string&amp;amp; varname);&lt;br /&gt;
 	variable_info::array_range get_variable_cfgs(const std::string&amp;amp; varname);&lt;br /&gt;
@@ -165,6 +165,7 @@&lt;br /&gt;
   rand_rng::simple_rng rng_ ;&lt;br /&gt;
 	config variables;&lt;br /&gt;
 	mutable config temporaries; // lengths of arrays, etc.&lt;br /&gt;
+	mutable string_map save_t_string;&lt;br /&gt;
 	const rand_rng::set_random_generator generator_setter; /**&amp;lt; Make sure that rng is initialized first */&lt;br /&gt;
 	friend struct variable_info;&lt;br /&gt;
 };&lt;br /&gt;
Index: src/variable.cpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/variable.cpp	(revision 33970)&lt;br /&gt;
+++ src/variable.cpp	(working copy)&lt;br /&gt;
@@ -713,7 +713,7 @@&lt;br /&gt;
 	}&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
-t_string&amp;amp; variable_info::as_scalar() {&lt;br /&gt;
+config::proxy_string variable_info::as_scalar() {&lt;br /&gt;
 	assert(is_valid);&lt;br /&gt;
 	return (*vars)[key];&lt;br /&gt;
 }&lt;br /&gt;
Index: src/multiplayer_connect.cpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/multiplayer_connect.cpp	(revision 33970)&lt;br /&gt;
+++ src/multiplayer_connect.cpp	(working copy)&lt;br /&gt;
@@ -1439,8 +1439,8 @@&lt;br /&gt;
 		int side_num = 1;&lt;br /&gt;
 		foreach (config &amp;amp;side, sides)&lt;br /&gt;
 		{&lt;br /&gt;
-			t_string &amp;amp;team_name = side[&amp;quot;team_name&amp;quot;];&lt;br /&gt;
-			t_string &amp;amp;user_team_name = side[&amp;quot;user_team_name&amp;quot;];&lt;br /&gt;
+			config::proxy_string team_name = side[&amp;quot;team_name&amp;quot;];&lt;br /&gt;
+			config::proxy_string user_team_name = side[&amp;quot;user_team_name&amp;quot;];&lt;br /&gt;
 &lt;br /&gt;
 			if(team_name.empty())&lt;br /&gt;
 				team_name = lexical_cast&amp;lt;std::string&amp;gt;(side_num);&lt;br /&gt;
@@ -1465,7 +1465,7 @@&lt;br /&gt;
 		foreach (config &amp;amp;side, sides)&lt;br /&gt;
 		{&lt;br /&gt;
 			const std::string side_num = lexical_cast&amp;lt;std::string&amp;gt;(_side_num);&lt;br /&gt;
-			t_string &amp;amp;team_name = side[&amp;quot;team_name&amp;quot;];&lt;br /&gt;
+			config::proxy_string team_name = side[&amp;quot;team_name&amp;quot;];&lt;br /&gt;
 &lt;br /&gt;
 			if(team_name.empty())&lt;br /&gt;
 				team_name = side_num;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Res</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_res&amp;diff=29032</id>
		<title>SummerOfCodeProposal res</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_res&amp;diff=29032"/>
		<updated>2009-03-22T15:13:37Z</updated>

		<summary type="html">&lt;p&gt;Res: New page: = A bit about me =  My name is Frank Richter, currently studying Computer Sciences at the University of Jena (that's in Germany).  As far as C++ is concerned, I program in it since at leas...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= A bit about me =&lt;br /&gt;
&lt;br /&gt;
My name is Frank Richter, currently studying Computer Sciences at the University of Jena (that's in Germany).&lt;br /&gt;
&lt;br /&gt;
As far as C++ is concerned, I program in it since at least seven years now. In my spare time I also develop for Crystal Space, an open source 3D engine. While I did a lot in the topics of realtime 3D, OpenGL, shaders and such, I also did (and do) 'low-level' things like cross-platform services and, last, but in this context here now certainly not least, matters of ''memory optimization''. &lt;br /&gt;
&lt;br /&gt;
= Current status =&lt;br /&gt;
&lt;br /&gt;
 * Upon reading the blog post linked in the idea proposal my first thought was to use a proxy class for operator[]. Below a patch that implements it.&lt;br /&gt;
&lt;br /&gt;
== Proxy class patch ==&lt;br /&gt;
&lt;br /&gt;
This builds and, I believe, works, but has a number of not-so-nice issues:&lt;br /&gt;
* Some places store return values in &amp;lt;pre&amp;gt;t_string&amp;amp;&amp;lt;/pre&amp;gt;. The idea is to change these to &amp;lt;pre&amp;gt;config::proxy_string&amp;lt;/pre&amp;gt;, as that type should ideally behave like &amp;lt;pre&amp;gt;t_string&amp;amp;&amp;lt;/pre&amp;gt;.&lt;br /&gt;
* &amp;lt;pre&amp;gt;config::proxy_string&amp;lt;/pre&amp;gt; can cast to both &amp;lt;pre&amp;gt;std::string&amp;lt;/pre&amp;gt; and &amp;lt;pre&amp;gt;t_string&amp;lt;/pre&amp;gt;.&lt;br /&gt;
The first is necessary as &amp;lt;pre&amp;gt;t_string&amp;lt;/pre&amp;gt; can cast to it as well; the second is necessary to&lt;br /&gt;
support use of a &amp;lt;pre&amp;gt;config::proxy_string&amp;lt;/pre&amp;gt; where a &amp;lt;pre&amp;gt;const t_string&amp;amp;&amp;lt;/pre&amp;gt; is expected.&lt;br /&gt;
Unfortunately, this introduces an ambiguity in cases where a &amp;lt;pre&amp;gt;config::proxy_string&amp;lt;/pre&amp;gt; is passed to methods that can take either of &amp;lt;pre&amp;gt;std::string&amp;lt;/pre&amp;gt; or &amp;lt;pre&amp;gt;t_string&amp;lt;/pre&amp;gt;.&lt;br /&gt;
* the &amp;lt;pre&amp;gt;variables_set&amp;lt;/pre&amp;gt; class has a member (&amp;lt;pre&amp;gt;get_variable_const()&amp;lt;/pre&amp;gt;) that returns a &amp;lt;pre&amp;gt;t_string&amp;amp;&amp;lt;/pre&amp;gt;. &amp;lt;pre&amp;gt;game_state&amp;lt;/pre&amp;gt; descends from this class; it's &amp;lt;pre&amp;gt;get_variable_const()&amp;lt;/pre&amp;gt; implementation supposedly returns a value from a &amp;lt;pre&amp;gt;config&amp;lt;/pre&amp;gt;. To ensure the ref is valid, the value as a &amp;lt;pre&amp;gt;t_string&amp;lt;/pre&amp;gt; is stored in a map. This is clearly not ideal.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Index: src/config.cpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/config.cpp	(revision 33970)&lt;br /&gt;
+++ src/config.cpp	(working copy)&lt;br /&gt;
@@ -293,10 +293,12 @@&lt;br /&gt;
 	delete res;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
+/*&lt;br /&gt;
 t_string&amp;amp; config::operator[](const std::string&amp;amp; key)&lt;br /&gt;
 {&lt;br /&gt;
 	return values[key];&lt;br /&gt;
 }&lt;br /&gt;
+*/&lt;br /&gt;
 &lt;br /&gt;
 const t_string&amp;amp; config::operator[](const std::string&amp;amp; key) const&lt;br /&gt;
 {&lt;br /&gt;
Index: src/font.cpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/font.cpp	(revision 33970)&lt;br /&gt;
+++ src/font.cpp	(working copy)&lt;br /&gt;
@@ -1278,7 +1278,7 @@&lt;br /&gt;
 		known_fonts.insert(font[&amp;quot;name&amp;quot;]);&lt;br /&gt;
 	}&lt;br /&gt;
 &lt;br /&gt;
-	font_order = (*fonts_config)[&amp;quot;order&amp;quot;];&lt;br /&gt;
+	font_order = (*fonts_config)[&amp;quot;order&amp;quot;].t_str();&lt;br /&gt;
 	const std::vector&amp;lt;std::string&amp;gt; font_order = utils::split((*fonts_config)[&amp;quot;order&amp;quot;]);&lt;br /&gt;
 	std::vector&amp;lt;font::subset_descriptor&amp;gt; fontlist;&lt;br /&gt;
 	std::vector&amp;lt;std::string&amp;gt;::const_iterator font;&lt;br /&gt;
Index: src/playsingle_controller.cpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/playsingle_controller.cpp	(revision 33970)&lt;br /&gt;
+++ src/playsingle_controller.cpp	(working copy)&lt;br /&gt;
@@ -281,7 +281,7 @@&lt;br /&gt;
 		// Log before prestart events: they do weird things.&lt;br /&gt;
 		if (first_human_team_ != -1) {&lt;br /&gt;
 			log.start(gamestate_, teams_[first_human_team_], first_human_team_ + 1, units_,&lt;br /&gt;
-					  loading_game_ ? gamestate_.get_variable(&amp;quot;turn_number&amp;quot;) : &amp;quot;&amp;quot;, status_.number_of_turns());&lt;br /&gt;
+					  loading_game_ ? gamestate_.get_variable(&amp;quot;turn_number&amp;quot;).c_str() : &amp;quot;&amp;quot;, status_.number_of_turns());&lt;br /&gt;
 		}&lt;br /&gt;
 &lt;br /&gt;
 		fire_prestart(!loading_game_);&lt;br /&gt;
Index: src/gamestatus.cpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/gamestatus.cpp	(revision 33970)&lt;br /&gt;
+++ src/gamestatus.cpp	(working copy)&lt;br /&gt;
@@ -1166,7 +1166,7 @@&lt;br /&gt;
 	}&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
-t_string&amp;amp; game_state::get_variable(const std::string&amp;amp; key)&lt;br /&gt;
+config::proxy_string game_state::get_variable(const std::string&amp;amp; key)&lt;br /&gt;
 {&lt;br /&gt;
 	return variable_info(key, true, variable_info::TYPE_SCALAR).as_scalar();&lt;br /&gt;
 }&lt;br /&gt;
@@ -1174,8 +1174,9 @@&lt;br /&gt;
 const t_string&amp;amp; game_state::get_variable_const(const std::string&amp;amp; key) const&lt;br /&gt;
 {&lt;br /&gt;
 	variable_info to_get(key, false, variable_info::TYPE_SCALAR);&lt;br /&gt;
-	if(!to_get.is_valid) return temporaries[key];&lt;br /&gt;
-	return to_get.as_scalar();&lt;br /&gt;
+	config::proxy_string val ((!to_get.is_valid) ? temporaries[key] : to_get.as_scalar());&lt;br /&gt;
+	save_t_string[key] = val.t_str();&lt;br /&gt;
+	return save_t_string[key];&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 config&amp;amp; game_state::get_variable_cfg(const std::string&amp;amp; key)&lt;br /&gt;
Index: src/theme.cpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/theme.cpp	(revision 33970)&lt;br /&gt;
+++ src/theme.cpp	(working copy)&lt;br /&gt;
@@ -169,13 +169,13 @@&lt;br /&gt;
 			// follow the inheritance hierarchy and push all the nodes on the stack&lt;br /&gt;
 			std::vector&amp;lt;const config*&amp;gt; parent_stack(1, (*i));&lt;br /&gt;
 			const config* parent;&lt;br /&gt;
-			const t_string* parent_id = &amp;amp;((**i)[&amp;quot;inherits&amp;quot;]);&lt;br /&gt;
-			while((parent = top_cfg.find_child(&amp;quot;resolution&amp;quot;, &amp;quot;id&amp;quot;, (*parent_id))) == NULL) {&lt;br /&gt;
-				parent = top_cfg.find_child(&amp;quot;partialresolution&amp;quot;, &amp;quot;id&amp;quot;, (*parent_id));&lt;br /&gt;
+			t_string parent_id = ((**i)[&amp;quot;inherits&amp;quot;]);&lt;br /&gt;
+			while((parent = top_cfg.find_child(&amp;quot;resolution&amp;quot;, &amp;quot;id&amp;quot;, parent_id)) == NULL) {&lt;br /&gt;
+				parent = top_cfg.find_child(&amp;quot;partialresolution&amp;quot;, &amp;quot;id&amp;quot;, parent_id);&lt;br /&gt;
 				if(parent == NULL)&lt;br /&gt;
-					throw config::error(&amp;quot;[partialresolution] refers to non-existant [resolution] &amp;quot; + (*parent_id).str());&lt;br /&gt;
+					throw config::error(&amp;quot;[partialresolution] refers to non-existant [resolution] &amp;quot; + parent_id.str());&lt;br /&gt;
 				parent_stack.push_back(parent);&lt;br /&gt;
-				parent_id = &amp;amp;((*parent)[&amp;quot;inherits&amp;quot;]);&lt;br /&gt;
+				parent_id = ((*parent)[&amp;quot;inherits&amp;quot;]);&lt;br /&gt;
 			}&lt;br /&gt;
 &lt;br /&gt;
 			// Add the parent resolution and apply all the modifications of its children&lt;br /&gt;
Index: src/variable.hpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/variable.hpp	(revision 33970)&lt;br /&gt;
+++ src/variable.hpp	(working copy)&lt;br /&gt;
@@ -206,7 +206,7 @@&lt;br /&gt;
 	 * Results: after deciding the desired type, these methods can retrieve the result&lt;br /&gt;
 	 * Note: first you should force_valid or check is_valid, otherwise these may fail&lt;br /&gt;
 	 */&lt;br /&gt;
-	t_string&amp;amp; as_scalar();&lt;br /&gt;
+	config::proxy_string as_scalar();&lt;br /&gt;
 	config&amp;amp; as_container();&lt;br /&gt;
 	array_range as_array(); //range may be empty&lt;br /&gt;
 };&lt;br /&gt;
Index: src/game_config.cpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/game_config.cpp	(revision 33970)&lt;br /&gt;
+++ src/game_config.cpp	(working copy)&lt;br /&gt;
@@ -239,7 +239,7 @@&lt;br /&gt;
 				std::string id = (**teamC)[&amp;quot;id&amp;quot;];&lt;br /&gt;
 				std::vector&amp;lt;Uint32&amp;gt; temp = string2rgb((**teamC)[&amp;quot;rgb&amp;quot;]);&lt;br /&gt;
 				team_rgb_range.insert(std::make_pair(id,color_range(temp)));&lt;br /&gt;
-				team_rgb_name[id] = (**teamC)[&amp;quot;name&amp;quot;];&lt;br /&gt;
+				team_rgb_name[id] = (**teamC)[&amp;quot;name&amp;quot;].t_str();&lt;br /&gt;
 				//generate palette of same name;&lt;br /&gt;
 				std::vector&amp;lt;Uint32&amp;gt; tp = palette(team_rgb_range[id]);&lt;br /&gt;
 				if(tp.size()){&lt;br /&gt;
Index: src/config.hpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/config.hpp	(revision 33970)&lt;br /&gt;
+++ src/config.hpp	(working copy)&lt;br /&gt;
@@ -150,6 +150,43 @@&lt;br /&gt;
 	private:&lt;br /&gt;
 		Itor i_;&lt;br /&gt;
 	};&lt;br /&gt;
+	&lt;br /&gt;
+	class proxy_string&lt;br /&gt;
+	{&lt;br /&gt;
+	  config&amp;amp; owner;&lt;br /&gt;
+	  const std::string&amp;amp; key;&lt;br /&gt;
+	  &lt;br /&gt;
+	  t_string&amp;amp; real_str() { return owner.values[key]; }&lt;br /&gt;
+	  const t_string&amp;amp; real_str() const { return owner.values[key]; }&lt;br /&gt;
+	public:&lt;br /&gt;
+	  proxy_string (config&amp;amp; owner, const std::string&amp;amp; key) : owner (owner), key (key) {}&lt;br /&gt;
+	&lt;br /&gt;
+	  proxy_string&amp;amp; operator= (const proxy_string&amp;amp; other)&lt;br /&gt;
+	  { return this-&amp;gt;operator= (other.real_str()); }&lt;br /&gt;
+	    &lt;br /&gt;
+	  proxy_string&amp;amp; operator= (const char* str)&lt;br /&gt;
+	  { real_str() = str; return *this; }&lt;br /&gt;
+	  proxy_string&amp;amp; operator= (const t_string&amp;amp; str)&lt;br /&gt;
+	  { real_str() = str; return *this; }&lt;br /&gt;
+	  proxy_string&amp;amp; operator= (const std::string&amp;amp; str)&lt;br /&gt;
+	  { real_str() = str; return *this; }&lt;br /&gt;
+	  &lt;br /&gt;
+	  proxy_string&amp;amp; operator+= (const std::string&amp;amp; str)&lt;br /&gt;
+	  { real_str() += str; return *this; }&lt;br /&gt;
+	  &lt;br /&gt;
+	  // t_string 'emulation' methods&lt;br /&gt;
+	  bool empty() const { return real_str().empty(); }&lt;br /&gt;
+	  const char* c_str() const { return real_str().c_str(); }&lt;br /&gt;
+	  std::string to_serialized() const { return real_str().to_serialized(); }&lt;br /&gt;
+	  &lt;br /&gt;
+	  const std::string&amp;amp; str() const { return real_str().str(); }&lt;br /&gt;
+	  const t_string&amp;amp; t_str() const { return real_str(); }&lt;br /&gt;
+	  operator std::string () const { return real_str().str(); }&lt;br /&gt;
+	  operator t_string() const { return real_str(); }&lt;br /&gt;
+	  &lt;br /&gt;
+	  inline friend std::ostream&amp;amp; operator&amp;lt;&amp;lt;(std::ostream&amp;amp; os, const proxy_string&amp;amp; str)&lt;br /&gt;
+	  { return os &amp;lt;&amp;lt; str.real_str(); }&lt;br /&gt;
+	};&lt;br /&gt;
 &lt;br /&gt;
 	typedef std::pair&amp;lt;const_attribute_iterator,const_attribute_iterator&amp;gt; const_attr_itors;&lt;br /&gt;
 &lt;br /&gt;
@@ -167,7 +204,10 @@&lt;br /&gt;
 	config&amp;amp; add_child(const std::string&amp;amp; key);&lt;br /&gt;
 	config&amp;amp; add_child(const std::string&amp;amp; key, const config&amp;amp; val);&lt;br /&gt;
 	config&amp;amp; add_child_at(const std::string&amp;amp; key, const config&amp;amp; val, size_t index);&lt;br /&gt;
-	t_string&amp;amp; operator[](const std::string&amp;amp; key);&lt;br /&gt;
+	&lt;br /&gt;
+	//t_string&amp;amp; operator[](const std::string&amp;amp; key);&lt;br /&gt;
+	proxy_string operator[](const std::string&amp;amp; key)&lt;br /&gt;
+	{ return proxy_string (*this, key); }&lt;br /&gt;
 	const t_string&amp;amp; operator[](const std::string&amp;amp; key) const;&lt;br /&gt;
 &lt;br /&gt;
 	const t_string&amp;amp; get_attribute(const std::string&amp;amp; key) const;&lt;br /&gt;
Index: src/game_events.cpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/game_events.cpp	(revision 33970)&lt;br /&gt;
+++ src/game_events.cpp	(working copy)&lt;br /&gt;
@@ -88,10 +88,10 @@&lt;br /&gt;
 	class pump_manager {&lt;br /&gt;
 		public:&lt;br /&gt;
 		pump_manager() :&lt;br /&gt;
-			x1_(state_of_game-&amp;gt;get_variable(&amp;quot;x1&amp;quot;)),&lt;br /&gt;
-			x2_(state_of_game-&amp;gt;get_variable(&amp;quot;x2&amp;quot;)),&lt;br /&gt;
-			y1_(state_of_game-&amp;gt;get_variable(&amp;quot;y1&amp;quot;)),&lt;br /&gt;
-			y2_(state_of_game-&amp;gt;get_variable(&amp;quot;y2&amp;quot;))&lt;br /&gt;
+			x1_(state_of_game-&amp;gt;get_variable(&amp;quot;x1&amp;quot;).str()),&lt;br /&gt;
+			x2_(state_of_game-&amp;gt;get_variable(&amp;quot;x2&amp;quot;).str()),&lt;br /&gt;
+			y1_(state_of_game-&amp;gt;get_variable(&amp;quot;y1&amp;quot;).str()),&lt;br /&gt;
+			y2_(state_of_game-&amp;gt;get_variable(&amp;quot;y2&amp;quot;).str())&lt;br /&gt;
 		{&lt;br /&gt;
 			++instance_count;&lt;br /&gt;
 		}&lt;br /&gt;
@@ -856,7 +856,7 @@&lt;br /&gt;
 &lt;br /&gt;
 	static void store_gold_side(bool store_side, const vconfig&amp;amp; cfg)&lt;br /&gt;
 	{&lt;br /&gt;
-		t_string *gold_store;&lt;br /&gt;
+		config::proxy_string *gold_store = 0;&lt;br /&gt;
 		std::string side = cfg[&amp;quot;side&amp;quot;];&lt;br /&gt;
 		std::string var_name = cfg[&amp;quot;variable&amp;quot;];&lt;br /&gt;
 		if(var_name.empty()) {&lt;br /&gt;
@@ -882,11 +882,12 @@&lt;br /&gt;
 				state_of_game-&amp;gt;get_variable(var_name+&amp;quot;.user_team_name&amp;quot;) = (*teams)[team_index].user_team_name();&lt;br /&gt;
 				state_of_game-&amp;gt;get_variable(var_name+&amp;quot;.colour&amp;quot;) = (*teams)[team_index].map_colour_to();&lt;br /&gt;
 &lt;br /&gt;
-				gold_store = &amp;amp;state_of_game-&amp;gt;get_variable(var_name+&amp;quot;.gold&amp;quot;);&lt;br /&gt;
+				gold_store = new config::proxy_string (state_of_game-&amp;gt;get_variable(var_name+&amp;quot;.gold&amp;quot;));&lt;br /&gt;
 			} else {&lt;br /&gt;
-				gold_store = &amp;amp;state_of_game-&amp;gt;get_variable(var_name);&lt;br /&gt;
+				gold_store = new config::proxy_string (state_of_game-&amp;gt;get_variable(var_name));&lt;br /&gt;
 			}&lt;br /&gt;
 			*gold_store = lexical_cast_default&amp;lt;std::string&amp;gt;((*teams)[team_index].gold(),&amp;quot;&amp;quot;);&lt;br /&gt;
+			delete gold_store;&lt;br /&gt;
 		}&lt;br /&gt;
 	}&lt;br /&gt;
 &lt;br /&gt;
@@ -1158,7 +1159,7 @@&lt;br /&gt;
 		assert(state_of_game != NULL);&lt;br /&gt;
 &lt;br /&gt;
 		const std::string name = cfg[&amp;quot;name&amp;quot;];&lt;br /&gt;
-		t_string&amp;amp; var = state_of_game-&amp;gt;get_variable(name);&lt;br /&gt;
+		config::proxy_string var = state_of_game-&amp;gt;get_variable(name);&lt;br /&gt;
 &lt;br /&gt;
 		const t_string&amp;amp; literal = cfg.get_attribute(&amp;quot;literal&amp;quot;);	// no $var substitution&lt;br /&gt;
 		if(literal.empty() == false) {&lt;br /&gt;
@@ -1191,7 +1192,7 @@&lt;br /&gt;
 &lt;br /&gt;
 		const std::string multiply = cfg[&amp;quot;multiply&amp;quot;];&lt;br /&gt;
 		if(multiply.empty() == false) {&lt;br /&gt;
-			if(isint(var) &amp;amp;&amp;amp; isint(multiply)) {&lt;br /&gt;
+			if(isint(var.str()) &amp;amp;&amp;amp; isint(multiply)) {&lt;br /&gt;
 				var = str_cast( std::atoi(var.c_str()) * std::atoi(multiply.c_str()) );&lt;br /&gt;
 			} else {&lt;br /&gt;
 				var = str_cast( std::atof(var.c_str()) * std::atof(multiply.c_str()) );&lt;br /&gt;
@@ -1204,7 +1205,7 @@&lt;br /&gt;
 				ERR_NG &amp;lt;&amp;lt; &amp;quot;division by zero on variable &amp;quot; &amp;lt;&amp;lt; name &amp;lt;&amp;lt; &amp;quot;\n&amp;quot;;&lt;br /&gt;
 				return;&lt;br /&gt;
 			}&lt;br /&gt;
-			if(isint(var) &amp;amp;&amp;amp; isint(divide)) {&lt;br /&gt;
+			if(isint(var.str()) &amp;amp;&amp;amp; isint(divide)) {&lt;br /&gt;
 				var = str_cast( std::atoi(var.c_str()) / std::atoi(divide.c_str()) );&lt;br /&gt;
 			} else {&lt;br /&gt;
 				var = str_cast( std::atof(var.c_str()) / std::atof(divide.c_str()) );&lt;br /&gt;
@@ -1217,7 +1218,7 @@&lt;br /&gt;
 				ERR_NG &amp;lt;&amp;lt; &amp;quot;division by zero on variable &amp;quot; &amp;lt;&amp;lt; name &amp;lt;&amp;lt; &amp;quot;\n&amp;quot;;&lt;br /&gt;
 				return;&lt;br /&gt;
 			}&lt;br /&gt;
-			if(isint(var) &amp;amp;&amp;amp; isint(modulo)) {&lt;br /&gt;
+			if(isint(var.str()) &amp;amp;&amp;amp; isint(modulo)) {&lt;br /&gt;
 				var = str_cast( std::atoi(var.c_str()) % std::atoi(modulo.c_str()) );&lt;br /&gt;
 			} else {&lt;br /&gt;
 				double value = std::fmod( std::atof(var.c_str()), std::atof(modulo.c_str()) );&lt;br /&gt;
Index: src/gui/dialogs/addon_list.cpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/gui/dialogs/addon_list.cpp	(revision 33970)&lt;br /&gt;
+++ src/gui/dialogs/addon_list.cpp	(working copy)&lt;br /&gt;
@@ -74,10 +74,10 @@&lt;br /&gt;
 		item[&amp;quot;label&amp;quot;] = tmp;&lt;br /&gt;
 		data.insert(std::make_pair(&amp;quot;author&amp;quot;, item));&lt;br /&gt;
 &lt;br /&gt;
-		item[&amp;quot;label&amp;quot;] = (**itor)[&amp;quot;downloads&amp;quot;];&lt;br /&gt;
+		item[&amp;quot;label&amp;quot;] = (**itor)[&amp;quot;downloads&amp;quot;].t_str();&lt;br /&gt;
 		data.insert(std::make_pair(&amp;quot;downloads&amp;quot;, item));&lt;br /&gt;
 &lt;br /&gt;
-		item[&amp;quot;label&amp;quot;] = (**itor)[&amp;quot;size&amp;quot;];&lt;br /&gt;
+		item[&amp;quot;label&amp;quot;] = (**itor)[&amp;quot;size&amp;quot;].t_str();&lt;br /&gt;
 		data.insert(std::make_pair(&amp;quot;size&amp;quot;, item));&lt;br /&gt;
 &lt;br /&gt;
 		list-&amp;gt;add_row(data);&lt;br /&gt;
Index: src/unit_types.cpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/unit_types.cpp	(revision 33970)&lt;br /&gt;
+++ src/unit_types.cpp	(working copy)&lt;br /&gt;
@@ -791,8 +791,8 @@&lt;br /&gt;
         build_created(cfg, mv_types, races, traits);&lt;br /&gt;
     }&lt;br /&gt;
 &lt;br /&gt;
-	type_name_ = cfg_[&amp;quot;name&amp;quot;];&lt;br /&gt;
-	description_ = cfg_[&amp;quot;description&amp;quot;];&lt;br /&gt;
+	type_name_ = cfg_[&amp;quot;name&amp;quot;].t_str();&lt;br /&gt;
+	description_ = cfg_[&amp;quot;description&amp;quot;].t_str();&lt;br /&gt;
 	hitpoints_ = lexical_cast_default&amp;lt;int&amp;gt;(cfg[&amp;quot;hitpoints&amp;quot;], 1);&lt;br /&gt;
 	level_ = lexical_cast_default&amp;lt;int&amp;gt;(cfg[&amp;quot;level&amp;quot;], 0);&lt;br /&gt;
 	movement_ = lexical_cast_default&amp;lt;int&amp;gt;(cfg[&amp;quot;movement&amp;quot;], 1);&lt;br /&gt;
Index: src/gamestatus.hpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/gamestatus.hpp	(revision 33970)&lt;br /&gt;
+++ src/gamestatus.hpp	(working copy)&lt;br /&gt;
@@ -120,7 +120,7 @@&lt;br /&gt;
 &lt;br /&gt;
 	// Variable access&lt;br /&gt;
 &lt;br /&gt;
-	t_string&amp;amp; get_variable(const std::string&amp;amp; varname);&lt;br /&gt;
+	config::proxy_string get_variable(const std::string&amp;amp; varname);&lt;br /&gt;
 	virtual const t_string&amp;amp; get_variable_const(const std::string&amp;amp; varname) const;&lt;br /&gt;
 	config&amp;amp; get_variable_cfg(const std::string&amp;amp; varname);&lt;br /&gt;
 	variable_info::array_range get_variable_cfgs(const std::string&amp;amp; varname);&lt;br /&gt;
@@ -165,6 +165,7 @@&lt;br /&gt;
   rand_rng::simple_rng rng_ ;&lt;br /&gt;
 	config variables;&lt;br /&gt;
 	mutable config temporaries; // lengths of arrays, etc.&lt;br /&gt;
+	mutable string_map save_t_string;&lt;br /&gt;
 	const rand_rng::set_random_generator generator_setter; /**&amp;lt; Make sure that rng is initialized first */&lt;br /&gt;
 	friend struct variable_info;&lt;br /&gt;
 };&lt;br /&gt;
Index: src/variable.cpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/variable.cpp	(revision 33970)&lt;br /&gt;
+++ src/variable.cpp	(working copy)&lt;br /&gt;
@@ -713,7 +713,7 @@&lt;br /&gt;
 	}&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
-t_string&amp;amp; variable_info::as_scalar() {&lt;br /&gt;
+config::proxy_string variable_info::as_scalar() {&lt;br /&gt;
 	assert(is_valid);&lt;br /&gt;
 	return (*vars)[key];&lt;br /&gt;
 }&lt;br /&gt;
Index: src/multiplayer_connect.cpp&lt;br /&gt;
===================================================================&lt;br /&gt;
--- src/multiplayer_connect.cpp	(revision 33970)&lt;br /&gt;
+++ src/multiplayer_connect.cpp	(working copy)&lt;br /&gt;
@@ -1439,8 +1439,8 @@&lt;br /&gt;
 		int side_num = 1;&lt;br /&gt;
 		foreach (config &amp;amp;side, sides)&lt;br /&gt;
 		{&lt;br /&gt;
-			t_string &amp;amp;team_name = side[&amp;quot;team_name&amp;quot;];&lt;br /&gt;
-			t_string &amp;amp;user_team_name = side[&amp;quot;user_team_name&amp;quot;];&lt;br /&gt;
+			config::proxy_string team_name = side[&amp;quot;team_name&amp;quot;];&lt;br /&gt;
+			config::proxy_string user_team_name = side[&amp;quot;user_team_name&amp;quot;];&lt;br /&gt;
 &lt;br /&gt;
 			if(team_name.empty())&lt;br /&gt;
 				team_name = lexical_cast&amp;lt;std::string&amp;gt;(side_num);&lt;br /&gt;
@@ -1465,7 +1465,7 @@&lt;br /&gt;
 		foreach (config &amp;amp;side, sides)&lt;br /&gt;
 		{&lt;br /&gt;
 			const std::string side_num = lexical_cast&amp;lt;std::string&amp;gt;(_side_num);&lt;br /&gt;
-			t_string &amp;amp;team_name = side[&amp;quot;team_name&amp;quot;];&lt;br /&gt;
+			config::proxy_string team_name = side[&amp;quot;team_name&amp;quot;];&lt;br /&gt;
 &lt;br /&gt;
 			if(team_name.empty())&lt;br /&gt;
 				team_name = side_num;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Res</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeIdeas&amp;diff=29028</id>
		<title>SummerOfCodeIdeas</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeIdeas&amp;diff=29028"/>
		<updated>2009-03-22T14:56:58Z</updated>

		<summary type="html">&lt;p&gt;Res: /* GSoC Student pages */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a compilation of ideas from ML. Needs to be refined (more detailed description, deliverables, workload estimation?):&lt;br /&gt;
&lt;br /&gt;
== I want to be one of your Google Summer of Code students, what should I do... ==&lt;br /&gt;
&lt;br /&gt;
Here is a quick list of things to do to get you started&lt;br /&gt;
* Create an account on gna.org&lt;br /&gt;
* Create an account on the wesnoth forum, and tell an admin on the IRC channel to mark is as a GSoC Student account (Admins are boucman, Ivanovic, mordante, Shadow_Master, Sirp and Turuk)&lt;br /&gt;
* Join the irc channel (#wesnoth-dev on irc.freenode.net) and introduce yourself. We will not give formal interviews, but we will clearly favor people we have learned to know during the selection process (basically communication via IRC is mandatory for our project! it is the main way of &amp;quot;every day communication&amp;quot; for Wesnoth. For the same reason, it's also a good idea to regularly read the [http://wesnoth.debian.net/?C=M;O=A IRC logs].).&lt;br /&gt;
&lt;br /&gt;
* Start a wiki page about your idea, add a link on the bottom of this page and add this information on it:&lt;br /&gt;
** List your account names (gna, forum, irc nick) so that we can recognize you&lt;br /&gt;
** Fill the questionnaire on this page: [[SoC_Information_for_Google#Does_your_organization_have_an_application_template_you_would_like_to_see_students_use.3F_If_so.2C_please_provide_it_now.| List of questions to answer]]&lt;br /&gt;
** Detail your idea as much as possible, look at other students pages, and please give milestones and studies you've done&lt;br /&gt;
** Add a link to the page at the bottom of this page&lt;br /&gt;
&lt;br /&gt;
* Though not mandatory, it is highly advisable to go to the [[EasyCoding]] and [[NotSoEasyCoding]] pages and implement one of these ideas (or any idea of similar scope) so we have an idea how you work. Be sure to use your gna account when submitting these patches so we know who it is coming from. You can also implement some features from our feature request database at gna. When you implement something, also list it on your own page with a reference to the patch.&lt;br /&gt;
&lt;br /&gt;
* For working on Wesnoth you have to be able to compile trunk. To do so you should have a look at the [[WesnothSVN|page about svn]] and afterwards [[CompilingWesnoth|compile Wesnoth svn]].&lt;br /&gt;
&lt;br /&gt;
* Once you have everything done here and think your idea is okay, go to [http://groups.google.com/group/google-summer-of-code-announce/web/guide-to-the-gsoc-web-app-for-student-applicants page at google] to submit your application. You have to submit it before '''Date to be supplied later''' or you have no chance to get in!&lt;br /&gt;
&lt;br /&gt;
== List of Ideas for the Project (Suggestions from the wesnoth developers) ==&lt;br /&gt;
&lt;br /&gt;
Here is only a short description of possible Ideas we have, each has a page of its own with a more detailed version on it.&lt;br /&gt;
&lt;br /&gt;
=== Optimize implementation of WML for memory usage ===&lt;br /&gt;
&lt;br /&gt;
Based on this idea: [http://dave.wesnoth.org/?p=9] optimize WML to minimize its memory usage. High memory usage has been a problem for Wesnoth, and this project will aim to reduce it.&lt;br /&gt;
&lt;br /&gt;
=== Implement campaign statistics reports on stats.wesnoth.org ===&lt;br /&gt;
&lt;br /&gt;
Wesnoth has an infrastructure which records details of campaigns that players play into a centralized MySQL database. However, we only have rudimentary reports based on this MySQL database available at this time, at [http://stats.wesnoth.org].&lt;br /&gt;
&lt;br /&gt;
This project would involve writing a stats reporting web site which would take the data from the MySQL database and produce reports in chart and table form. Campaign designers would be able to use these reports to gather feedback on their campaigns and get ideas for improvements.&lt;br /&gt;
&lt;br /&gt;
A student could largely make their choice of infrastructure for creating the Website -- whether they prefer Python, Perl, Ruby, PHP, etc. This is a great opportunity for someone who doesn't want to dive into hardcore C++ to make a valuable contribution to Wesnoth.&lt;br /&gt;
&lt;br /&gt;
[[SoC Ideas Stats Server]] - Full Version of the idea, with detailed information&lt;br /&gt;
&lt;br /&gt;
=== Extending the Multiplayer server ===&lt;br /&gt;
&lt;br /&gt;
Our multiplayer community is generally strong and healthy, but we believe its growth is limited by some problems in the interface of the multiplayer lobby.&lt;br /&gt;
&lt;br /&gt;
[[SoC Ideas Multiplayer server]] - Full version of the idea, with detailed information&lt;br /&gt;
&lt;br /&gt;
=== Addon server ===&lt;br /&gt;
Wesnoth has an addon server which offers users to upload user &lt;br /&gt;
made content (UMC). This allows all other users of Wesnoth&lt;br /&gt;
to easily download and install this content. The server was &lt;br /&gt;
originally written for user-made campaigns but contains a lot&lt;br /&gt;
more types of addons nowadays. Both the server side and the &lt;br /&gt;
client side need to be improved.&lt;br /&gt;
&lt;br /&gt;
[[SoC Ideas Addon Server]] - Full version of the idea, with detailed information&lt;br /&gt;
&lt;br /&gt;
=== WML validation schemes ===&lt;br /&gt;
Wesnoth uses WML as basic data structure. Over the years&lt;br /&gt;
this language has evolved and got more complex. At the&lt;br /&gt;
moment the WML is validated at runtime and in case of a&lt;br /&gt;
problem the engine stops. With schemes these problems can&lt;br /&gt;
be validated when loading the WML, making it easier to find&lt;br /&gt;
problems before running into them.&lt;br /&gt;
&lt;br /&gt;
[[SoC Ideas Schemes]] - Full version of the idea, with detailed information&lt;br /&gt;
&lt;br /&gt;
=== Write a primitive library for Formula AI ===&lt;br /&gt;
&lt;br /&gt;
Wesnoth has always had a simple C++ based AI. David (our lead developer) has been working on a simple language to write AI in Wesnoth: [[FormulaAI]]&lt;br /&gt;
&lt;br /&gt;
The Wesnoth AI is used as an opponent in most campaigns, and as such is an important piece of code for the Wesnoth project. Unfortunately, because the skills required to understand and modify it are rather arcane, it is also one of the most neglected parts of the Wesnoth code. This is a place where a lot of research and useful work could be done. But keep in mind that [[WhyWritingAWesnothAIIsHard|writing an AI for Wesnoth is difficult]].&lt;br /&gt;
&lt;br /&gt;
Writing a whole AI is so complicated that we believe it can't be done in a single Summer of code. All proposals should keep that in mind and try to identify an interesting subset that would be workable in the limited time of a summer of code&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[SoC Ideas FormulaAI]] - Full version of the idea, with detailed information&lt;br /&gt;
&lt;br /&gt;
=== Savegame reorganization ===&lt;br /&gt;
The savegame formats of Wesnoth for single player campaigns&lt;br /&gt;
and multiplayer differ from each other. And they are processed&lt;br /&gt;
differently as well. Now there is an additional request coming&lt;br /&gt;
up: Multiplayer campaigns. The task will be to unify the savegames&lt;br /&gt;
for all types of scenarios in order to provide a maintainable code&lt;br /&gt;
again.&lt;br /&gt;
&lt;br /&gt;
[[SoC Ideas Savegame]] - Full version of the idea, with detailed information&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Other possible ideas to be fleshed out ===&lt;br /&gt;
A MapGenerator rewrite - better scalable for outdoor maps, plus the possibility to define areas (similar to the caverns in the cave generator) etc.&lt;br /&gt;
&lt;br /&gt;
=== Make your own ideas ===&lt;br /&gt;
If you have your own idea the best thing is to join IRC wesnoth-dev at irc.freenode.net and discuss the idea with the developers there. If the developers think your idea is interesting and like the feature you can start to turn it into a full proposal. Once done discuss it again on IRC so the developers can accept your idea.&lt;br /&gt;
&lt;br /&gt;
== Information about our Project ==&lt;br /&gt;
The information we provided google with about our project can be looked up at the site [[SoC Information for Google]].&lt;br /&gt;
&lt;br /&gt;
Also see the [[DeveloperResources]] link (from the [[Project]] page).&lt;br /&gt;
&lt;br /&gt;
== People to bug on IRC ==&lt;br /&gt;
We have prepared a list of people with their &amp;quot;area of competence&amp;quot;. This is to give you an idea on which areas those people can be of help for you. Of course you should always just ask in the IRC chan, but those are the most likely ones to answer questions in the respective area. And here is the list:&lt;br /&gt;
&lt;br /&gt;
[[SoC People to bug on IRC]]&lt;br /&gt;
&lt;br /&gt;
== GSoC Student pages ==&lt;br /&gt;
&lt;br /&gt;
Please add a link to your wiki page below&lt;br /&gt;
&lt;br /&gt;
[[SummerOfCodeProposal_Velory| Velory - SoC Proposal]]&lt;br /&gt;
&lt;br /&gt;
[[SummerOfCodeProposal_AI_Improvement_Crab| Crab - SoC Proposal - AI Improvement]]&lt;br /&gt;
&lt;br /&gt;
[[SummerOfCodeProposal_Sparksteel | Sparksteel - Improving the AI engine design]]&lt;br /&gt;
&lt;br /&gt;
[[SummerOfCodeProposal_Euschn | Euschn - Savegame reorganization]]&lt;br /&gt;
&lt;br /&gt;
[[SummerOfCodeProposal_rubend | rubend - Extending the Multiplayer server]]&lt;br /&gt;
&lt;br /&gt;
[[SummerOfCodeProposal_Ryochan7| Ryochan7 - Addon server]]&lt;br /&gt;
&lt;br /&gt;
[[SummerOfCodeProposal_iyonius| iyonius - Addon server]]&lt;br /&gt;
&lt;br /&gt;
[[SummerOfCodeProposal_res| res -  Optimize implementation of WML for memory usage ]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Summer of Code|*]]&lt;/div&gt;</summary>
		<author><name>Res</name></author>
		
	</entry>
</feed>