(svn r9324) [gamebalance] -Sync: r9314:9322 from trunk (newhouses) gamebalance
authorcelestar
Mon, 19 Mar 2007 12:49:55 +0000
branchgamebalance
changeset 9896 2473804114de
parent 9895 7bd07f43b0e3
child 9897 4a2d75b60786
(svn r9324) [gamebalance] -Sync: r9314:9322 from trunk (newhouses)
docs/landscape.html
docs/landscape_externals.html
docs/landscape_grid.html
projects/openttd.vcproj
projects/openttd_vs80.vcproj
source.list
src/aircraft_cmd.cpp
src/map.cpp
src/map.h
src/misc.cpp
src/misc_gui.cpp
src/newgrf.cpp
src/newgrf.h
src/newgrf_callbacks.h
src/newgrf_house.cpp
src/newgrf_house.h
src/newgrf_sound.cpp
src/newgrf_sound.h
src/newgrf_spritegroup.cpp
src/newgrf_spritegroup.h
src/newgrf_town.cpp
src/newgrf_town.h
src/openttd.cpp
src/saveload.cpp
src/table/sprites.h
src/table/town_land.h
src/town.h
src/town_cmd.cpp
src/town_map.h
src/train_cmd.cpp
src/void_map.h
src/water_cmd.cpp
--- a/docs/landscape.html	Mon Mar 19 12:38:16 2007 +0000
+++ b/docs/landscape.html	Mon Mar 19 12:49:55 2007 +0000
@@ -568,621 +568,67 @@
    <td valign=top nowrap>&nbsp;</td>
    <td>
     <ul>
-     <li>m2: Index into the array of towns</li>
-     <li>m3 bits 7..6: stage of construction (<tt>3</tt> = completed)</li>
-     <li>m4: <a name="HouseTypes">town building type</a>:<br>
-      <small>Note: In the climate list, 'sub-arctic' means below the snow line, and 'snow' means above the snow line in the sub-arctic climate.</small>
-      <table>
-       <tr>
-        <th align=left>Type&nbsp;</th>
-        <th align=left>Size&nbsp;</th>
-        <th align=left>Climates&nbsp;</th>
-        <th align=left>Description</th>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>00</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>temperate</td>
-        <td align=left>tall office block</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>01</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>temperate</td>
-        <td align=left>office block</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>02</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>temperate</td>
-        <td align=left>small block of flats</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>03</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>temperate</td>
-        <td align=left>church</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>04</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>temperate, sub-arctic, sub-tropical</td>
-        <td align=left>large office block</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>05</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>snow</td>
-        <td align=left>large office block</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>06</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>temperate</td>
-        <td align=left>town houses</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>07</tt>..<tt>08</tt>&nbsp; </td>
-        <td>1&times;2</td>
-        <td>temperate</td>
-        <td align=left>hotel</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>09</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>temperate, sub-arctic, sub-tropical&nbsp;&nbsp;</td>
-        <td align=left>statue</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>0A</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>temperate, sub-arctic, sub-tropical</td>
-        <td align=left>fountain</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>0B</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>temperate</td>
-        <td align=left>park (with a pond)</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>0C</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>temperate</td>
-        <td align=left>park (with an alley)</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>0D</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>temperate</td>
-        <td align=left>office block</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>0E</tt>..<tt>10</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>temperate</td>
-        <td align=left>various types of shops and offices</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>11</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>temperate, sub-arctic, sub-tropical</td>
-        <td align=left>modern office building</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>12</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>temperate</td>
-        <td align=left>warehouse</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>13</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>temperate</td>
-        <td align=left>office block (with spiral stairway on the side)</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>14</tt>..<tt>17</tt>&nbsp; </td>
-        <td>2&times;2</td>
-        <td>temperate</td>
-        <td align=left>stadium</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>18</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>temperate</td>
-        <td align=left>old houses</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>19</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>temperate</td>
-        <td align=left>cottages</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>1A</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>temperate</td>
-        <td align=left>houses</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>1B</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>temperate</td>
-        <td align=left>flats</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>1C</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>temperate</td>
-        <td align=left>tall office block</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>1D</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>temperate</td>
-        <td align=left>shops and offices</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>1E</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>temperate, sub-tropical</td>
-        <td align=left>shops and offices</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>1F</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>temperate</td>
-        <td align=left>theatre</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>20</tt>..<tt>23</tt>&nbsp; </td>
-        <td>2&times;2</td>
-        <td>temperate, sub-arctic, sub-tropical</td>
-        <td align=left>stadium (modern style)</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>24</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>temperate, sub-arctic, sub-tropical</td>
-        <td align=left>offices (the modern 'vertical tube' style)</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>25</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>sub-arctic</td>
-        <td align=left>houses</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>26</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>snow</td>
-        <td align=left>houses</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>27</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>temperate</td>
-        <td align=left>cinema</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>28</tt>..<tt>2B</tt>&nbsp; </td>
-        <td>2&times;2</td>
-        <td>temperate</td>
-        <td align=left>shopping mall</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>2C</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>sub-arctic</td>
-        <td align=left>flats</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>2D</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>snow</td>
-        <td align=left>flats</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>2E</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>sub-arctic</td>
-        <td align=left>houses</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>2F</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>snow</td>
-        <td align=left>houses</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>30</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>sub-arctic</td>
-        <td align=left>houses</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>31</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>snow</td>
-        <td align=left>houses</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>32</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>sub-arctic, sub-tropical</td>
-        <td align=left>tall office block</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>33</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>snow</td>
-        <td align=left>tall office block</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>34</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>sub-arctic</td>
-        <td align=left>tall office block</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>35</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>snow</td>
-        <td align=left>tall office block</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>36</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>sub-arctic, sub-tropical</td>
-        <td align=left>tall office block</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>37</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>snow</td>
-        <td align=left>tall office block</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>38</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>sub-arctic</td>
-        <td align=left>houses</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>39</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>snow</td>
-        <td align=left>houses</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>3A</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>sub-arctic</td>
-        <td align=left>shops and offices</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>3B</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>snow</td>
-        <td align=left>shops and offices</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>3C</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>sub-arctic</td>
-        <td align=left>church</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>3D</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>snow</td>
-        <td align=left>church</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>3E</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>sub-arctic</td>
-        <td align=left>houses</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>3F</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>snow</td>
-        <td align=left>houses</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>40</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>sub-arctic</td>
-        <td align=left>shops and offices</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>41</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>snow</td>
-        <td align=left>shops and offices</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>42</tt>..<tt>43</tt>&nbsp; </td>
-        <td>1&times;2</td>
-        <td>sub-arctic</td>
-        <td align=left>hotel</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>44</tt>..<tt>45</tt>&nbsp; </td>
-        <td>1&times;2</td>
-        <td>snow</td>
-        <td align=left>hotel</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>46</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>sub-arctic, sub-tropical</td>
-        <td align=left>shops and offices</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>47</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>snow</td>
-        <td align=left>shops and offices</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>48</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>sub-arctic</td>
-        <td align=left>tall office block</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>49</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>snow</td>
-        <td align=left>tall office block</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>4A</tt>..<tt>4B</tt>&nbsp; </td>
-        <td>2&times;1</td>
-        <td>sub-arctic</td>
-        <td align=left>tall office block</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>4C</tt>..<tt>4D</tt>&nbsp; </td>
-        <td>2&times;1</td>
-        <td>snow</td>
-        <td align=left>tall office block</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>4E</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>sub-tropical</td>
-        <td align=left>houses (with a tree in a corner)</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>4F</tt>, <tt>50</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>sub-tropical</td>
-        <td align=left>houses</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>51</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>sub-tropical</td>
-        <td align=left>houses (suburb-type)</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>52</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>sub-tropical</td>
-        <td align=left>flats</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>53</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>sub-tropical</td>
-        <td align=left>church</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>54</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>sub-tropical</td>
-        <td align=left>houses (with two trees in front)</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>55</tt>, <tt>56</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>sub-tropical</td>
-        <td align=left>flats</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>57</tt>..<tt>58</tt>&nbsp; </td>
-        <td>2&times;1</td>
-        <td>sub-tropical</td>
-        <td align=left>tall office block</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>59</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>sub-tropical</td>
-        <td align=left>flats</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>5A</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>sub-tropical</td>
-        <td align=left>tall office block</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>5B</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>toyland</td>
-        <td align=left>church</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>5C</tt>..<tt>61</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>toyland</td>
-        <td align=left>various types of toyland houses</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>62</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>toyland</td>
-        <td align=left>tall office block</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>63</tt>..<tt>64</tt>&nbsp; </td>
-        <td>1&times;2</td>
-        <td>toyland</td>
-        <td align=left>houses ('shoe' style)</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>65</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>toyland</td>
-        <td align=left>tall office block</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>66</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>toyland</td>
-        <td align=left>igloo</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>67</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>toyland</td>
-        <td align=left>tepees</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>68</tt>, <tt>69</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>toyland</td>
-        <td align=left>shops and offices</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>6A</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>toyland</td>
-        <td align=left>tall office block</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>6B</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>toyland</td>
-        <td align=left>statue</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>6C</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>toyland</td>
-        <td align=left>teapot-house</td>
-       </tr>
-
-       <tr>
-        <td nowrap valign=top><tt>6D</tt>&nbsp; </td>
-        <td>1&times;1</td>
-        <td>toyland</td>
-        <td align=left>piggy-bank</td>
-       </tr>
-      </table>
-     </li>
-     <li>m5 bits 2..0: construction counter, for buildings under construction incremented on every periodic tile processing<br>
-         On wraparound the stage of construction in m3 is increased
-     </li>
-     <li>for large office blocks (types <tt>04</tt> and <tt>05</tt>):
+     <li>m1 : Random bits <a href="#newhouses">(newhouses)</a> </li>
+     <li>m2 : index into the array of industries</li>
+     <li>m3 bit 7 :
       <ul>
-       <li>m1 bits 6..0: position of the lift</li>
-       <li>m1 bit 7: if set the lift is moving</li>
-       <li>m5 bit 7: if set then m5 bits 5..0 hold the destination floor of the lift, which could be 0..6, except 1.<br>
-           So the building has 6 effective floors. This is due to the fact that the first floor is 2 'normal' floors high.<br>
-           One 'normal' floor has a height of 6 lift positions.</li>
+       <li> set : House is complete
+        <ul>
+         <li>m5 : age of House. Maximum been 255, which means 255 years and more</li>
+        </ul>
+       </li>
+       <li> clear : House is in construction
+        <ul>
+         <li>m5 bits 7..5 : free</li>
+         <li>m5 bits 4..3 : construction stage</li>
+         <li>m5 bits 2..0 : construction counter</li>
+        </ul>
+       </li>
+      </ul>
+     <li>m3 bit 6 : 9th bit of house type (m4), allowing 512 different types.</li>
+     <li>m3 bits 5..0 : triggers activated <a href="#newhouses">(newhouses)</a></li>
+     <li>m4 : <a href="landscape_externals.html">town building type</a> (with m3[6] bit)</li>
+     <li>m5 : see m3 bit 7</li>
+     <li>m6 :
+      <ul>
+       <li>If <a href="#newhouses">newhouses</a> is activated
+        <ul>
+         <li>bits 7..3 : Current animation frame</li>
+         <li>bit 2 : free</li>
+        </ul>
+       </li>
+       <li>Standard behaviour
+        <ul>
+         <li>bits 7..2 : lift position (for houses type 04 and 05)</li>
+        </ul>
+       </li>
+       <li>bits 1..0 : tropic zone specifier</li>
       </ul>
      </li>
-     <li>m6 bits 1..0 : <a href="#tropic_zone">Tropic zone definition</a></li>
+     <li>m7 :
+      <ul>
+       <li>If <a href="#newhouses">newhouses</a> is activated
+        <ul>
+         <li>Periodic processing time remaining</li>
+        </ul>
+       </li>
+       <li>Standard behaviour (only for houses type 04 and 05)
+        <ul>
+         <li>bits 7..4 : free</li>
+         <li>bits 3..1 : lift destination.  Values can be 0..6, except 1.<br>
+             So the building has 6 effective floors. This is due to the fact that the first floor is 2 'normal' floors high.<br>
+             One 'normal' floor has a height of 6 lift positions.
+         </li>
+         <li>bit 0 : Lift has destination when set</li>
+        </ul>
+       </li>
+      </ul>
+     </li>
     </ul>
+    <small><a name="newhouses">Newhouses is the name englobing a newGRF feature developped by TTDPatch devs (mainly Csaboka).<br>
+    It allows the replacement of the properties as well as the graphics of houses in the game.<br>
+    To distinguish between the standard behaviour and the newGRF one, HouseID (m4 + m3[6]) is tested for anything above 110.<br>
+    110 is the count of standard houses. So above 110 means there is a new definition of at least one house</small>
    </td>
   </tr>
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/landscape_externals.html	Mon Mar 19 12:49:55 2007 +0000
@@ -0,0 +1,616 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+
+<head>
+ <meta name="Author" content="Marcin Grzegorczyk">
+ <meta name="Description" content="Structure of OpenTTD (OTTD) landscape arrays">
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <title>OpenTTD Landscape externals</title>
+</head>
+
+<body>
+ <h3><a name="Landscape">Landscape</a></h3>
+ <p>
+ These are the different house types available on standard game.<br>
+ <small>Note: In the climate list, 'sub-arctic' means below the snow line, and 'snow' means above the snow line in the sub-arctic climate.</small>
+ </p>
+
+ <table>
+  <tr>
+   <th align=left>Type&nbsp;</th>
+   <th align=left>Size&nbsp;</th>
+   <th align=left>Climates&nbsp;</th>
+   <th align=left>Description</th>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>00</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>temperate</td>
+   <td align=left>tall office block</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>01</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>temperate</td>
+   <td align=left>office block</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>02</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>temperate</td>
+   <td align=left>small block of flats</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>03</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>temperate</td>
+   <td align=left>church</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>04</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>temperate, sub-arctic, sub-tropical</td>
+   <td align=left>large office block</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>05</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>snow</td>
+   <td align=left>large office block</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>06</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>temperate</td>
+   <td align=left>town houses</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>07</tt>..<tt>08</tt>&nbsp; </td>
+   <td>1&times;2</td>
+   <td>temperate</td>
+   <td align=left>hotel</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>09</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>temperate, sub-arctic, sub-tropical&nbsp;&nbsp;</td>
+   <td align=left>statue</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>0A</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>temperate, sub-arctic, sub-tropical</td>
+   <td align=left>fountain</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>0B</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>temperate</td>
+   <td align=left>park (with a pond)</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>0C</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>temperate</td>
+   <td align=left>park (with an alley)</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>0D</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>temperate</td>
+   <td align=left>office block</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>0E</tt>..<tt>10</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>temperate</td>
+   <td align=left>various types of shops and offices</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>11</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>temperate, sub-arctic, sub-tropical</td>
+   <td align=left>modern office building</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>12</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>temperate</td>
+   <td align=left>warehouse</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>13</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>temperate</td>
+   <td align=left>office block (with spiral stairway on the side)</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>14</tt>..<tt>17</tt>&nbsp; </td>
+   <td>2&times;2</td>
+   <td>temperate</td>
+   <td align=left>stadium</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>18</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>temperate</td>
+   <td align=left>old houses</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>19</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>temperate</td>
+   <td align=left>cottages</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>1A</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>temperate</td>
+   <td align=left>houses</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>1B</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>temperate</td>
+   <td align=left>flats</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>1C</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>temperate</td>
+   <td align=left>tall office block</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>1D</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>temperate</td>
+   <td align=left>shops and offices</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>1E</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>temperate, sub-tropical</td>
+   <td align=left>shops and offices</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>1F</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>temperate</td>
+   <td align=left>theatre</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>20</tt>..<tt>23</tt>&nbsp; </td>
+   <td>2&times;2</td>
+   <td>temperate, sub-arctic, sub-tropical</td>
+   <td align=left>stadium (modern style)</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>24</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>temperate, sub-arctic, sub-tropical</td>
+   <td align=left>offices (the modern 'vertical tube' style)</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>25</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>sub-arctic</td>
+   <td align=left>houses</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>26</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>snow</td>
+   <td align=left>houses</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>27</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>temperate</td>
+   <td align=left>cinema</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>28</tt>..<tt>2B</tt>&nbsp; </td>
+   <td>2&times;2</td>
+   <td>temperate</td>
+   <td align=left>shopping mall</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>2C</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>sub-arctic</td>
+   <td align=left>flats</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>2D</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>snow</td>
+   <td align=left>flats</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>2E</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>sub-arctic</td>
+   <td align=left>houses</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>2F</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>snow</td>
+   <td align=left>houses</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>30</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>sub-arctic</td>
+   <td align=left>houses</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>31</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>snow</td>
+   <td align=left>houses</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>32</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>sub-arctic, sub-tropical</td>
+   <td align=left>tall office block</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>33</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>snow</td>
+   <td align=left>tall office block</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>34</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>sub-arctic</td>
+   <td align=left>tall office block</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>35</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>snow</td>
+   <td align=left>tall office block</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>36</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>sub-arctic, sub-tropical</td>
+   <td align=left>tall office block</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>37</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>snow</td>
+   <td align=left>tall office block</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>38</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>sub-arctic</td>
+   <td align=left>houses</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>39</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>snow</td>
+   <td align=left>houses</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>3A</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>sub-arctic</td>
+   <td align=left>shops and offices</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>3B</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>snow</td>
+   <td align=left>shops and offices</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>3C</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>sub-arctic</td>
+   <td align=left>church</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>3D</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>snow</td>
+   <td align=left>church</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>3E</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>sub-arctic</td>
+   <td align=left>houses</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>3F</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>snow</td>
+   <td align=left>houses</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>40</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>sub-arctic</td>
+   <td align=left>shops and offices</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>41</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>snow</td>
+   <td align=left>shops and offices</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>42</tt>..<tt>43</tt>&nbsp; </td>
+   <td>1&times;2</td>
+   <td>sub-arctic</td>
+   <td align=left>hotel</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>44</tt>..<tt>45</tt>&nbsp; </td>
+   <td>1&times;2</td>
+   <td>snow</td>
+   <td align=left>hotel</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>46</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>sub-arctic, sub-tropical</td>
+   <td align=left>shops and offices</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>47</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>snow</td>
+   <td align=left>shops and offices</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>48</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>sub-arctic</td>
+   <td align=left>tall office block</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>49</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>snow</td>
+   <td align=left>tall office block</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>4A</tt>..<tt>4B</tt>&nbsp; </td>
+   <td>2&times;1</td>
+   <td>sub-arctic</td>
+   <td align=left>tall office block</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>4C</tt>..<tt>4D</tt>&nbsp; </td>
+   <td>2&times;1</td>
+   <td>snow</td>
+   <td align=left>tall office block</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>4E</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>sub-tropical</td>
+   <td align=left>houses (with a tree in a corner)</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>4F</tt>, <tt>50</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>sub-tropical</td>
+   <td align=left>houses</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>51</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>sub-tropical</td>
+   <td align=left>houses (suburb-type)</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>52</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>sub-tropical</td>
+   <td align=left>flats</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>53</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>sub-tropical</td>
+   <td align=left>church</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>54</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>sub-tropical</td>
+   <td align=left>houses (with two trees in front)</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>55</tt>, <tt>56</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>sub-tropical</td>
+   <td align=left>flats</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>57</tt>..<tt>58</tt>&nbsp; </td>
+   <td>2&times;1</td>
+   <td>sub-tropical</td>
+   <td align=left>tall office block</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>59</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>sub-tropical</td>
+   <td align=left>flats</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>5A</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>sub-tropical</td>
+   <td align=left>tall office block</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>5B</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>toyland</td>
+   <td align=left>church</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>5C</tt>..<tt>61</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>toyland</td>
+   <td align=left>various types of toyland houses</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>62</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>toyland</td>
+   <td align=left>tall office block</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>63</tt>..<tt>64</tt>&nbsp; </td>
+   <td>1&times;2</td>
+   <td>toyland</td>
+   <td align=left>houses ('shoe' style)</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>65</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>toyland</td>
+   <td align=left>tall office block</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>66</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>toyland</td>
+   <td align=left>igloo</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>67</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>toyland</td>
+   <td align=left>tepees</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>68</tt>, <tt>69</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>toyland</td>
+   <td align=left>shops and offices</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>6A</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>toyland</td>
+   <td align=left>tall office block</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>6B</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>toyland</td>
+   <td align=left>statue</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>6C</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>toyland</td>
+   <td align=left>teapot-house</td>
+  </tr>
+
+  <tr>
+   <td nowrap valign=top><tt>6D</tt>&nbsp; </td>
+   <td>1&times;1</td>
+   <td>toyland</td>
+   <td align=left>piggy-bank</td>
+  </tr>
+ </table>
+</body>
+
+</html>
\ No newline at end of file
--- a/docs/landscape_grid.html	Mon Mar 19 12:38:16 2007 +0000
+++ b/docs/landscape_grid.html	Mon Mar 19 12:49:55 2007 +0000
@@ -33,6 +33,7 @@
   <li><span style="font-weight: bold;">m4</span> - 8 bits in size, is used for general storage</li>
   <li><span style="font-weight: bold;">m5</span> - 8 bits in size, is used for general storage</li>
   <li><span style="font-weight: bold;">m6</span> - 8 bits in size, special meaning : lower 2 bits only valid in tropic climate, upper 2 bits for bridges</li>
+  <li><span style="font-weight: bold;">m7</span> - 8 bits in size, is used for general storage</li>
 </ul>
 
 <table align=center border="1" cellpadding="2" cellspacing="2">
@@ -46,6 +47,7 @@
       <th>m4 (8)</th>
       <th>m5 (8)</th>
       <th>m6 (8)</th>
+      <th>m7 (8)</th>
     </tr>
     <tr>
       <td colspan=2 class="caption">bits</td>
@@ -56,6 +58,7 @@
       <td class="bits">7654 3210</td>
       <td class="bits">7654 3210</td>
       <td class="bits">7654 3210</td>
+      <td class="bits">7654 3210</td>
     </tr>
     <tr>
       <td rowspan="2">0</td>
@@ -67,6 +70,7 @@
       <td class="bits">XXXX XX<span class="free">OO</span></td>
       <td class="bits">XXXX XXXX</td>
       <td class="bits">XX<span class="free">OO OO</span>XX</td>
+      <td class="bits"><span class="free">OOOO OOOO</span></td>
     </tr>
     <tr>
       <td class="caption">farmland</td>
@@ -77,6 +81,7 @@
       <td class="bits">-inherit-</td>
       <td class="bits"><span class="free">OOO</span>X XXXX</td>
       <td class="bits">XX<span class="free">OO OO</span>XX</td>
+      <td class="bits"><span class="free">OOOO OOOO</span></td>
     </tr>
     <tr>
       <td rowspan=3>1</td>
@@ -88,6 +93,7 @@
       <td class="bits"><span class="free">OOOO O</span>XXX</td>
       <td class="bits">XXXX XXXX</td>
       <td class="bits">XX<span class="free">OO OO</span>XX</td>
+      <td class="bits"><span class="free">OOOO OOOO</span></td>
     </tr>
     <tr>
       <td class="caption">depot</td>
@@ -98,6 +104,7 @@
       <td class="bits"><span class="free">OOOO</span> XXXX</td>
       <td class="bits">XX<span class="free">OO O</span>XXX</td>
       <td class="bits">XX<span class="free">OO OO</span>XX</td>
+      <td class="bits"><span class="free">OOOO OOOO</span></td>
     </tr>
     <tr>
       <td class="caption">waypoint</td>
@@ -108,6 +115,7 @@
       <td class="bits"><span class="free">OOOO</span> XXXX</td>
       <td class="bits">XX<span class="free">OO O</span>XXX</td>
       <td class="bits">XX<span class="free">OO OO</span>XX</td>
+      <td class="bits"><span class="free">OOOO OOOO</span></td>
     </tr>
     <tr>
       <td rowspan=3>2</td>
@@ -119,6 +127,7 @@
       <td class="bits">XXXX XXXX</td>
       <td class="bits">XXXX XXXX</td>
       <td class="bits">XX<span class="free">OO OO</span>XX</td>
+      <td class="bits"><span class="free">OOOO OOOO</span></td>
     </tr>
     <tr>
       <td class="caption">level crossing</td>
@@ -129,6 +138,7 @@
       <td class="bits">XXXX XXXX</td>
       <td class="bits">XXXX XX<span class="free">OO</span></td>
       <td class="bits">XX<span class="free">OO OO</span>XX</td>
+      <td class="bits"><span class="free">OOOO OOOO</span></td>
     </tr>
     <tr>
       <td class="caption">road depot</td>
@@ -139,17 +149,19 @@
       <td class="bits"><span class="free">OOOO OOOO</span></td>
       <td class="bits">XXXX XXXX</td>
       <td class="bits">XX<span class="free">OO OO</span>XX</td>
+      <td class="bits"><span class="free">OOOO OOOO</span></td>
     </tr>
     <tr>
       <td>3</td>
-      <td class="caption">town</td>
+      <td class="caption">house</td>
       <td class="bits">XXXX XXXX</td>
-      <td class="bits"><span class="abuse">XXXX XXXX</span></td>
+      <td class="bits">XXXX XXXX</td>
       <td class="bits">XXXX XXXX XXXX XXXX</td>
-      <td class="bits">XX<span class="free">OO OOOO</span></td>
+      <td class="bits">XX<span class="free">O</span>X XXXX</td>
       <td class="bits">XXXX XXXX</td>
-      <td class="bits">X<span class="free">O</span>XX XXXX</td>
-      <td class="bits"><span class="free">OOOO OO</span>XX</td>
+      <td class="bits">XX<span class="abuse">XX XXXX</span></td>
+      <td class="bits"><span class="abuse">XXXX XX</span>XX</td>
+      <td class="bits"><span class="abuse">X</span>XX<span class="abuse">X XXX</span>X</td>
     </tr>
     <tr>
       <td>4</td>
@@ -161,6 +173,7 @@
       <td class="bits">XXXX XX<span class="free">OO</span></td>
       <td class="bits">XX<span class="free">OO O</span>XXX</td>
       <td class="bits"><span class="free">OOOO OO</span>XX</td>
+      <td class="bits"><span class="free">OOOO OOOO</span></td>
     </tr>
     <tr>
       <td>5</td>
@@ -172,6 +185,7 @@
       <td class="bits">XXXX XXXX</td>
       <td class="bits">XXXX XXXX</td>
       <td class="bits"><span class="free">OOOO O</span>XXX</td>
+      <td class="bits"><span class="free">OOOO OOOO</span></td>
     </tr>
     <tr>
       <td>6</td>
@@ -183,20 +197,25 @@
       <td class="bits"><span class="free">OOOO OOOO</span></td>
       <td class="bits"><span class="free">OOOO OO</span>XX</td>
       <td class="bits">XX<span class="free">OO OO</span>XX</td>
+      <td class="bits"><span class="free">OOOO OOOO</span></td>
     </tr>
     <tr>
       <td rowspan=3>8</td>
       <td class="caption">industry</td>
       <td class="bits">XXXX XXXX</td>
-      <td class="bits"><span class="abuse">X</span><span class="free">OO</span><span class="abuse">X XXXX</span></td>
+      <td class="bits"><span class="abuse">X</span><span class="free">OO</span><span class="abuse">X
+        XXXX</span></td>
       <td class="bits">XXXX XXXX XXXX XXXX</td>
       <td class="bits"><span class="free">OOOO OOOO</span></td>
       <td class="bits"><span class="free">OOOO OOOO</span></td>
       <td class="bits">XXXX XXXX</td>
       <td class="bits"><span class="free">OOOO OO</span>XX</td>
+      <td class="bits"><span class="free">OOOO OOOO</span></td>
     </tr>
     <tr>
-      <td>bubble/sugar/toffee,<BR>gold/copper/coal,<BR>oil wells, power station</td>
+      <td>bubble/sugar/toffee,<BR>
+        gold/copper/coal,<BR>
+        oil wells, power station</td>
       <td class="bits">-inherit-</td>
       <td class="bits"><span class="abuse">X</span><span class="free">OOO OOOO</span></td>
       <td class="bits">-inherit-</td>
@@ -204,6 +223,7 @@
       <td class="bits"><span class="free">OOOO OOOO</span></td>
       <td class="bits">-inherit-</td>
       <td class="bits">-inherit-</td>
+      <td class="bits"><span class="free">OOOO OOOO</span></td>
     </tr>
     <tr>
       <td>toy factory</td>
@@ -214,6 +234,7 @@
       <td class="bits">XXXX XXXX</td>
       <td class="bits">-inherit-</td>
       <td class="bits">-inherit-</td>
+      <td class="bits"><span class="free">OOOO OOOO</span></td>
     </tr>
     <tr>
       <td rowspan=2>9</td>
@@ -225,16 +246,19 @@
       <td class="bits">X<span class="free">OOO OOOO</span></td>
       <td class="bits">X<span class="free">OOO</span> XXXX</td>
       <td class="bits">XX<span class="free">OO OO</span>XX</td>
+      <td class="bits"><span class="free">OOOO OOOO</span></td>
     </tr>
     <tr>
       <td>bridge ramp</td>
       <td class="bits">XXXX XXXX</td>
       <td class="bits">XXXX XXXX</td>
-      <td class="bits"><span class="free">OOOO OOOO</span> <span class="abuse">XXXX</span> <span class="free">OOOO</span></td>
+      <td class="bits"><span class="free">OOOO OOOO</span> <span class="abuse">XXXX</span>
+        <span class="free">OOOO</span></td>
       <td class="bits"><span class="free">OOOO</span> XXXX</td>
       <td class="bits">X<span class="free">OOO OOOO</span></td>
       <td class="bits">X<span class="free">OOO</span> XXXX</td>
       <td class="bits">XX<span class="free">OO OO</span>XX</td>
+      <td class="bits"><span class="free">OOOO OOOO</span></td>
     </tr>
     <tr>
       <td>A</td>
@@ -246,6 +270,7 @@
       <td class="bits"><span class="free">OOOO OOOO</span></td>
       <td class="bits">XXXX XXXX</td>
       <td class="bits">XX<span class="free">OO OO</span>XX</td>
+      <td class="bits"><span class="free">OOOO OOOO</span></td>
     </tr>
   </tbody>
 </table>
--- a/projects/openttd.vcproj	Mon Mar 19 12:38:16 2007 +0000
+++ b/projects/openttd.vcproj	Mon Mar 19 12:49:55 2007 +0000
@@ -519,6 +519,9 @@
 				RelativePath=".\..\src\newgrf_engine.h">
 			</File>
 			<File
+				RelativePath=".\..\src\newgrf_house.h">
+			</File>
+			<File
 				RelativePath=".\..\src\newgrf_sound.h">
 			</File>
 			<File
@@ -531,6 +534,9 @@
 				RelativePath=".\..\src\newgrf_text.h">
 			</File>
 			<File
+				RelativePath=".\..\src\newgrf_town.h">
+			</File>
+			<File
 				RelativePath=".\..\src\news.h">
 			</File>
 			<File
@@ -926,6 +932,9 @@
 				RelativePath=".\..\src\newgrf_engine.cpp">
 			</File>
 			<File
+				RelativePath=".\..\src\newgrf_house.cpp">
+			</File>
+			<File
 				RelativePath=".\..\src\newgrf_sound.cpp">
 			</File>
 			<File
@@ -937,6 +946,9 @@
 			<File
 				RelativePath=".\..\src\newgrf_text.cpp">
 			</File>
+			<File
+				RelativePath=".\..\src\newgrf_town.cpp">
+			</File>
 		</Filter>
 		<Filter
 			Name="Map Accessors"
--- a/projects/openttd_vs80.vcproj	Mon Mar 19 12:38:16 2007 +0000
+++ b/projects/openttd_vs80.vcproj	Mon Mar 19 12:49:55 2007 +0000
@@ -448,11 +448,11 @@
 				>
 			</File>
 			<File
-				RelativePath=".\..\src\aystar.cpp"
+				RelativePath=".\..\src\autoreplace_cmd.cpp"
 				>
 			</File>
 			<File
-				RelativePath=".\..\src\autoreplace_cmd.cpp"
+				RelativePath=".\..\src\aystar.cpp"
 				>
 			</File>
 			<File
@@ -920,6 +920,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\newgrf_house.h"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\newgrf_sound.h"
 				>
 			</File>
@@ -936,6 +940,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\newgrf_town.h"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\news.h"
 				>
 			</File>
@@ -1456,6 +1464,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\newgrf_house.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\newgrf_sound.cpp"
 				>
 			</File>
@@ -1471,6 +1483,10 @@
 				RelativePath=".\..\src\newgrf_text.cpp"
 				>
 			</File>
+			<File
+				RelativePath=".\..\src\newgrf_town.cpp"
+				>
+			</File>
 		</Filter>
 		<Filter
 			Name="Map Accessors"
--- a/source.list	Mon Mar 19 12:38:16 2007 +0000
+++ b/source.list	Mon Mar 19 12:49:55 2007 +0000
@@ -141,10 +141,12 @@
 newgrf_cargo.h
 newgrf_config.h
 newgrf_engine.h
+newgrf_house.h
 newgrf_sound.h
 newgrf_spritegroup.h
 newgrf_station.h
 newgrf_text.h
+newgrf_town.h
 news.h
 npf.h
 music/null_m.h
@@ -280,10 +282,12 @@
 newgrf.cpp
 newgrf_config.cpp
 newgrf_engine.cpp
+newgrf_house.cpp
 newgrf_sound.cpp
 newgrf_spritegroup.cpp
 newgrf_station.cpp
 newgrf_text.cpp
+newgrf_town.cpp
 
 # Map Accessors
 bridge_map.cpp
--- a/src/aircraft_cmd.cpp	Mon Mar 19 12:38:16 2007 +0000
+++ b/src/aircraft_cmd.cpp	Mon Mar 19 12:49:55 2007 +0000
@@ -1369,7 +1369,7 @@
 	InvalidateWindow(WC_VEHICLE_VIEW, v->index);
 
 	uint amt = 2;
-	if (v->cargo_type == CT_PASSENGERS) amt += v->cargo_count;
+	if (IsCargoInClass(v->cargo_type, CC_PASSENGERS)) amt += v->cargo_count;
 	SetDParam(0, amt);
 
 	v->cargo_count = 0;
--- a/src/map.cpp	Mon Mar 19 12:38:16 2007 +0000
+++ b/src/map.cpp	Mon Mar 19 12:49:55 2007 +0000
@@ -22,7 +22,8 @@
 uint _map_tile_mask;
 uint _map_size;
 
-Tile* _m = NULL;
+Tile *_m = NULL;
+TileExtended *_me = NULL;
 
 
 void AllocateMap(uint size_x, uint size_y)
@@ -44,10 +45,16 @@
 	_map_tile_mask = _map_size - 1;
 
 	free(_m);
-	_m = CallocT<Tile>(_map_size);
+	free(_me);
 
-	/* XXX TODO handle memory shortage more gracefully */
-	if (_m == NULL) error("Failed to allocate memory for the map");
+	_m = CallocT<Tile>(_map_size);
+ 	_me = CallocT<TileExtended>(_map_size);
+
+ 	/* XXX @todo handle memory shortage more gracefully
+ 	 * Maybe some attemps could be made to try with smaller maps down to 64x64
+ 	 * Maybe check for available memory before doing the calls, after all, we know how big
+ 	 * the map is */
+	if ((_m == NULL) || (_me == NULL)) error("Failed to allocate memory for the map");
 }
 
 
--- a/src/map.h	Mon Mar 19 12:38:16 2007 +0000
+++ b/src/map.h	Mon Mar 19 12:49:55 2007 +0000
@@ -28,7 +28,12 @@
 	byte m6;
 };
 
-extern Tile* _m;
+struct TileExtended {
+	byte m7;
+};
+
+extern Tile *_m;
+extern TileExtended *_me;
 
 void AllocateMap(uint size_x, uint size_y);
 
--- a/src/misc.cpp	Mon Mar 19 12:38:16 2007 +0000
+++ b/src/misc.cpp	Mon Mar 19 12:49:55 2007 +0000
@@ -19,6 +19,7 @@
 #include "vehicle_gui.h"
 #include "variables.h"
 #include "ai/ai.h"
+#include "newgrf_house.h"
 #include "date.h"
 #include "cargotype.h"
 
@@ -134,6 +135,7 @@
 	InitializeSigns();
 	InitializeStations();
 	InitializeIndustries();
+	InitializeBuildingCounts();
 	InitializeMainGui();
 
 	InitializeNameMgr();
@@ -580,6 +582,34 @@
 	}
 }
 
+static void Load_MAP7()
+{
+	uint size = MapSize();
+	uint i;
+
+	for (i = 0; i != size;) {
+		uint8 buf[4096];
+		uint j;
+
+		SlArray(buf, lengthof(buf), SLE_UINT8);
+		for (j = 0; j != lengthof(buf); j++) _me[i++].m7 = buf[j];
+	}
+}
+
+static void Save_MAP7()
+{
+	uint size = MapSize();
+	uint i;
+
+	SlSetLength(size);
+	for (i = 0; i != size;) {
+		uint8 buf[4096];
+		uint j;
+
+		for (j = 0; j != lengthof(buf); j++) buf[j] = _me[i++].m7;
+		SlArray(buf, lengthof(buf), SLE_UINT8);
+	}
+}
 
 static void Save_CHTS()
 {
@@ -616,6 +646,7 @@
 	{ 'M3HI', Save_MAP4,     Load_MAP4,     CH_RIFF },
 	{ 'MAP5', Save_MAP5,     Load_MAP5,     CH_RIFF },
 	{ 'MAPE', Save_MAP6,     Load_MAP6,     CH_RIFF },
+	{ 'MAP7', Save_MAP7,     Load_MAP7,     CH_RIFF },
 
 	{ 'NAME', Save_NAME,     Load_NAME,     CH_ARRAY},
 	{ 'DATE', SaveLoad_DATE, SaveLoad_DATE, CH_RIFF},
--- a/src/misc_gui.cpp	Mon Mar 19 12:38:16 2007 +0000
+++ b/src/misc_gui.cpp	Mon Mar 19 12:49:55 2007 +0000
@@ -188,6 +188,7 @@
 	DEBUG(misc, LANDINFOD_LEVEL, "m4           = %#x", _m[tile].m4);
 	DEBUG(misc, LANDINFOD_LEVEL, "m5           = %#x", _m[tile].m5);
 	DEBUG(misc, LANDINFOD_LEVEL, "m6           = %#x", _m[tile].m6);
+	DEBUG(misc, LANDINFOD_LEVEL, "m7           = %#x", _me[tile].m7);
 #undef LANDINFOD_LEVEL
 }
 
--- a/src/newgrf.cpp	Mon Mar 19 12:38:16 2007 +0000
+++ b/src/newgrf.cpp	Mon Mar 19 12:49:55 2007 +0000
@@ -18,6 +18,7 @@
 #include "string.h"
 #include "table/strings.h"
 #include "bridge.h"
+#include "town.h"
 #include "economy.h"
 #include "newgrf_engine.h"
 #include "vehicle.h"
@@ -28,9 +29,11 @@
 #include "currency.h"
 #include "sound.h"
 #include "newgrf_config.h"
+#include "newgrf_house.h"
 #include "newgrf_sound.h"
 #include "newgrf_spritegroup.h"
 #include "helpers.hpp"
+#include "table/town_land.h"
 #include "cargotype.h"
 
 /* TTDPatch extended GRF format codec
@@ -68,6 +71,9 @@
 /* Set if any vehicle is loaded which uses 2cc (two company colours) */
 bool _have_2cc = false;
 
+/* Set if there are any newhouses loaded. */
+bool _have_newhouses = false;
+
 /* Default cargo translation table. By default there are 27 possible cargo types */
 static const uint _default_cargo_max = 27;
 static CargoLabel _default_cargo_list[_default_cargo_max];
@@ -227,6 +233,32 @@
 }
 
 
+/** Used when setting an object's property to map to the GRF's strings
+ * while taking in consideration the "drift" between TTDPatch string system and OpenTTD's one
+ * @param str StringID that we want to have the equivalent in OoenTTD
+ * @return the properly adjusted StringID
+ */
+static StringID MapGRFStringID(StringID str)
+{
+	/* 0xD0 and 0xDC stand for all the TextIDs in the range
+	*  of 0xD000 (misc graphics texts) and 0xDC00 (misc persistent texts).
+	 * These strings are unique to each grf file, and thus require to be used with the
+	 * grfid in which they are declared */
+	if (GB(str, 8, 8) == 0xD0 || GB(str, 8, 8) == 0xDC) {
+		return GetGRFStringID(_cur_grffile->grfid, str);
+	}
+
+	/* Map building names according to our lang file changes
+	 * 0x200F = Tall Office Block, first house name in the original data, the one that TTDPatch stil uses
+	 * 0x201F = Old houses is the last house name.
+	 * OpenTTD does not have exactly the same order aymore, so, the code below allows
+	 * to compensate for the difference */
+	if (str >= 0x200F && str <= 0x201F) return str + (STR_200F_TALL_OFFICE_BLOCK - 0x200F);
+
+	return str;
+}
+
+
 typedef bool (*VCI_Handler)(uint engine, int numinfo, int prop, byte **buf, int len);
 
 #define FOR_EACH_OBJECT for (i = 0; i < numinfo; i++)
@@ -1168,6 +1200,206 @@
 	return ret;
 }
 
+static bool TownHouseChangeInfo(uint hid, int numinfo, int prop, byte **bufp, int len)
+{
+	HouseSpec **housespec;
+	byte *buf = *bufp;
+	int i;
+	bool ret = false;
+
+	if (hid + numinfo >= HOUSE_MAX) {
+		grfmsg(1, "TownHouseChangeInfo: Too many houses loaded (%u), max (%u). Ignoring.", hid + numinfo, HOUSE_MAX-1);
+		return false;
+	}
+
+	/* Allocate house specs if they haven't been allocated already. */
+	if (_cur_grffile->housespec == NULL) {
+		_cur_grffile->housespec = CallocT<HouseSpec*>(HOUSE_MAX);
+
+		/* Reset any overrides that have been set. */
+		ResetHouseOverrides();
+	}
+
+	housespec = &_cur_grffile->housespec[hid];
+
+	if (prop != 0x08) {
+		/* Check that all the houses being modified have been defined. */
+		FOR_EACH_OBJECT {
+			if (housespec[i] == NULL) {
+				grfmsg(2, "TownHouseChangeInfo: Attempt to modify undefined house %u. Ignoring.", hid + i);
+				return false;
+			}
+		}
+	}
+
+	switch (prop) {
+		case 0x08: // Substitute building type, and definition of a new house
+			FOR_EACH_OBJECT {
+				byte subs_id = grf_load_byte(&buf);
+
+				if (subs_id == 0xFF) {
+					/* Instead of defining a new house, a substitute house id
+					 * of 0xFF disables the old house with the current id. */
+					_house_specs[hid + i].enabled = false;
+					continue;
+				} else if (subs_id >= NEW_HOUSE_OFFSET) {
+					/* The substitute id must be one of the original houses. */
+					grfmsg(2, "TownHouseChangeInfo: Attempt to use new house %u as substitute house for %u. Ignoring.", subs_id, hid + i);
+					return false;
+				}
+
+				/* Allocate space for this house. */
+				if (housespec[i] == NULL) housespec[i] = CallocT<HouseSpec>(1);
+
+				memcpy(housespec[i], &_house_specs[subs_id], sizeof(_house_specs[subs_id]));
+
+				housespec[i]->enabled = true;
+				housespec[i]->local_id = hid + i;
+				housespec[i]->substitute_id = subs_id;
+				housespec[i]->random_colour[0] = 0x04;  // those 4 random colours are the base colour
+				housespec[i]->random_colour[1] = 0x08;  // for all new houses
+				housespec[i]->random_colour[2] = 0x0C;  // they stand for red, blue, orange and green
+				housespec[i]->random_colour[3] = 0x06;
+
+				/* New houses do not (currently) expect to have a default start
+				 * date before 1930, as this breaks the build date stuff. See
+				 * FinaliseHouseArray() for more details. */
+				if (housespec[i]->min_date < 1930) housespec[i]->min_date = 1930;
+			}
+			_have_newhouses = true;
+			break;
+
+		case 0x09: // Building flags
+			FOR_EACH_OBJECT {
+				byte state = grf_load_byte(&buf);
+				housespec[i]->building_flags = (BuildingFlags)state;
+			}
+			break;
+
+		case 0x0A: // Availability years
+			FOR_EACH_OBJECT {
+				uint16 years = grf_load_word(&buf);
+				housespec[i]->min_date = GB(years, 0, 8) > 150 ? MAX_YEAR : ORIGINAL_BASE_YEAR + GB(years, 0, 8);
+				housespec[i]->max_date = GB(years, 8, 8) > 150 ? MAX_YEAR : ORIGINAL_BASE_YEAR + GB(years, 8, 8);
+			}
+			break;
+
+		case 0x0B: // Population
+			FOR_EACH_OBJECT housespec[i]->population = grf_load_byte(&buf);
+			break;
+
+		case 0x0C: // Mail generation multiplier
+			FOR_EACH_OBJECT housespec[i]->mail_generation = grf_load_byte(&buf);
+			break;
+
+		case 0x0D: // Passenger acceptance
+			FOR_EACH_OBJECT housespec[i]->passenger_acceptance = grf_load_byte(&buf);
+			break;
+
+		case 0x0E: // Mail acceptance
+			FOR_EACH_OBJECT housespec[i]->mail_acceptance = grf_load_byte(&buf);
+			break;
+
+		case 0x0F: // Goods, food or fizzy drinks acceptance
+			FOR_EACH_OBJECT {
+				int8 goods = grf_load_byte(&buf);
+				if (goods > 0) {
+					housespec[i]->goods_acceptance = goods;
+				} else {
+					housespec[i]->food_acceptance = -goods;
+				}
+			}
+			break;
+
+		case 0x10: // Local authority rating decrease on removal
+			FOR_EACH_OBJECT housespec[i]->remove_rating_decrease = grf_load_word(&buf);
+			break;
+
+		case 0x11: // Removal cost multiplier
+			FOR_EACH_OBJECT housespec[i]->removal_cost = grf_load_byte(&buf);
+			break;
+
+		case 0x12: // Building name ID
+			FOR_EACH_OBJECT housespec[i]->building_name = MapGRFStringID(grf_load_word(&buf));
+			break;
+
+		case 0x13: // Building availability mask
+			FOR_EACH_OBJECT {
+				uint16 avail = grf_load_word(&buf);
+				housespec[i]->building_availability = (HouseZones)avail;
+			}
+			break;
+
+		case 0x14: // House callback flags
+			FOR_EACH_OBJECT housespec[i]->callback_mask = grf_load_byte(&buf);
+			break;
+
+		case 0x15: // House override byte
+			FOR_EACH_OBJECT {
+				byte override = grf_load_byte(&buf);
+
+				/* The house being overridden must be an original house. */
+				if (override >= NEW_HOUSE_OFFSET) {
+					grfmsg(2, "TownHouseChangeInfo: Attempt to override new house %u with house id %u. Ignoring.", override, hid);
+					return false;
+				}
+
+				AddHouseOverride(hid, override);
+			}
+			break;
+
+		case 0x16: // Periodic refresh multiplier
+			FOR_EACH_OBJECT housespec[i]->processing_time = grf_load_byte(&buf);
+			break;
+
+		case 0x17: // Four random colours to use
+			FOR_EACH_OBJECT {
+				uint j;
+				for (j = 0; j < 4; j++)	housespec[i]->random_colour[j] = grf_load_byte(&buf);
+			}
+			break;
+
+		case 0x18: // Relative probability of appearing
+			FOR_EACH_OBJECT housespec[i]->probability = grf_load_byte(&buf);
+			break;
+
+		case 0x19: // Extra flags
+			FOR_EACH_OBJECT {
+				byte flags = grf_load_byte(&buf);
+				housespec[i]->extra_flags = (HouseExtraFlags)flags;
+			}
+			break;
+
+		case 0x1A: // Animation frames
+			FOR_EACH_OBJECT housespec[i]->animation_frames = grf_load_byte(&buf);
+			break;
+
+		case 0x1B: // Animation speed
+			FOR_EACH_OBJECT housespec[i]->animation_speed = clamp(grf_load_byte(&buf), 2, 16);
+			break;
+
+		case 0x1C: // Class of the building type
+			FOR_EACH_OBJECT housespec[i]->class_id = AllocateHouseClassID(grf_load_byte(&buf), _cur_grffile->grfid);
+			break;
+
+		case 0x1D: // Callback flags 2
+			FOR_EACH_OBJECT housespec[i]->callback_mask |= (grf_load_byte(&buf) << 8);
+			break;
+
+		case 0x1E: // Accepted cargo types
+			FOR_EACH_OBJECT grf_load_dword(&buf);
+			ret = true;
+			break;
+
+		default:
+			ret = true;
+			break;
+	}
+
+	*bufp = buf;
+	return ret;
+}
+
 static bool GlobalVarChangeInfo(uint gvid, int numinfo, int prop, byte **bufp, int len)
 {
 	byte *buf = *bufp;
@@ -1375,7 +1607,7 @@
 		/* GSF_STATION */      StationChangeInfo,
 		/* GSF_CANAL */        NULL,
 		/* GSF_BRIDGE */       BridgeChangeInfo,
-		/* GSF_TOWNHOUSE */    NULL,
+		/* GSF_TOWNHOUSE */    TownHouseChangeInfo,
 		/* GSF_GLOBALVAR */    GlobalVarChangeInfo,
 		/* GSF_INDUSTRYTILES */NULL,
 		/* GSF_INDUSTRIES */   NULL,
@@ -1853,6 +2085,86 @@
 					break;
 				}
 
+				case GSF_TOWNHOUSE: {
+					byte sprites     = _cur_grffile->spriteset_numents;
+					byte num_sprites = max((uint8)1, type);
+					uint i;
+
+					group = AllocateSpriteGroup();
+					group->type = SGT_TILELAYOUT;
+					group->g.layout.num_sprites = sprites;
+					group->g.layout.dts = CallocT<DrawTileSprites>(1);
+
+					/* Groundsprite */
+					group->g.layout.dts->ground_sprite = grf_load_word(&buf);
+					group->g.layout.dts->ground_pal    = grf_load_word(&buf);
+					/* Remap transparent/colour modifier bits */
+					if (HASBIT(group->g.layout.dts->ground_sprite, 14)) {
+						CLRBIT(group->g.layout.dts->ground_sprite, 14);
+						SETBIT(group->g.layout.dts->ground_sprite, PALETTE_MODIFIER_TRANSPARENT);
+					}
+					if (HASBIT(group->g.layout.dts->ground_sprite, 15)) {
+						CLRBIT(group->g.layout.dts->ground_sprite, 15);
+						SETBIT(group->g.layout.dts->ground_sprite, PALETTE_MODIFIER_COLOR);
+					}
+					if (HASBIT(group->g.layout.dts->ground_pal, 14)) {
+						CLRBIT(group->g.layout.dts->ground_pal, 14);
+						SETBIT(group->g.layout.dts->ground_sprite, SPRITE_MODIFIER_OPAQUE);
+					}
+					if (HASBIT(group->g.layout.dts->ground_pal, 15)) {
+						/* Bit 31 set means this is a custom sprite, so rewrite it to the
+						 * last spriteset defined. */
+						SpriteID sprite = _cur_grffile->spriteset_start + GB(group->g.layout.dts->ground_sprite, 0, 14) * sprites;
+						SB(group->g.layout.dts->ground_sprite, 0, SPRITE_WIDTH, sprite);
+						CLRBIT(group->g.layout.dts->ground_pal, 15);
+					}
+
+					group->g.layout.dts->seq = CallocT<DrawTileSeqStruct>(num_sprites + 1);
+
+					for (i = 0; i < num_sprites; i++) {
+						DrawTileSeqStruct *seq = (DrawTileSeqStruct*)&group->g.layout.dts->seq[i];
+
+						seq->image = grf_load_word(&buf);
+						seq->pal   = grf_load_word(&buf);
+						seq->delta_x = grf_load_byte(&buf);
+						seq->delta_y = grf_load_byte(&buf);
+
+						if (HASBIT(seq->image, 14)) {
+							CLRBIT(seq->image, 14);
+							SETBIT(seq->image, PALETTE_MODIFIER_TRANSPARENT);
+						}
+						if (HASBIT(seq->image, 15)) {
+							CLRBIT(seq->image, 15);
+							SETBIT(seq->image, PALETTE_MODIFIER_COLOR);
+						}
+						if (HASBIT(seq->pal, 14)) {
+							CLRBIT(seq->pal, 14);
+							SETBIT(seq->image, SPRITE_MODIFIER_OPAQUE);
+						}
+						if (HASBIT(seq->pal, 15)) {
+							/* Bit 31 set means this is a custom sprite, so rewrite it to the
+							 * last spriteset defined. */
+							SpriteID sprite = _cur_grffile->spriteset_start + GB(seq->image, 0, 14) * sprites;
+							SB(seq->image, 0, SPRITE_WIDTH, sprite);
+							CLRBIT(seq->pal, 15);
+						}
+
+						if (type > 0) {
+							seq->delta_z = grf_load_byte(&buf);
+							if ((byte)seq->delta_z == 0x80) continue;
+						}
+
+						seq->size_x = grf_load_byte(&buf);
+						seq->size_y = grf_load_byte(&buf);
+						seq->size_z = grf_load_byte(&buf);
+					}
+
+					/* Set the terminator value. */
+					((DrawTileSeqStruct*)group->g.layout.dts->seq)[i].delta_x = (byte)0x80;
+
+					break;
+				}
+
 				/* Loading of Tile Layout and Production Callback groups would happen here */
 				default: grfmsg(1, "NewSpriteGroup: Unsupported feature %d, skipping", feature);
 			}
@@ -1934,7 +2246,7 @@
 	grfmsg(6, "FeatureMapSpriteGroup: Feature %d, %d ids, %d cids, wagon override %d",
 			feature, idcount, cidcount, wagover);
 
-	if (feature > GSF_STATION) {
+	if (feature > GSF_STATION && feature != GSF_TOWNHOUSE) {
 		grfmsg(1, "FeatureMapSpriteGroup: Unsupported feature %d, skipping", feature);
 		return;
 	}
@@ -1986,6 +2298,29 @@
 			}
 		}
 		return;
+	} else if (feature == GSF_TOWNHOUSE) {
+		byte *bp = &buf[4 + idcount + cidcount * 3];
+		uint16 groupid = grf_load_word(&bp);
+
+		if (groupid >= _cur_grffile->spritegroups_count || _cur_grffile->spritegroups[groupid] == NULL) {
+			grfmsg(1, "FeatureMapSpriteGroup: Spriteset 0x%04X out of range 0x%X or empty, skipping.",
+			       groupid, _cur_grffile->spritegroups_count);
+			return;
+		}
+
+		for (uint i = 0; i < idcount; i++) {
+			uint8 hid = buf[3 + i];
+			HouseSpec *hs = _cur_grffile->housespec[hid];
+
+			if (hs == NULL) {
+				grfmsg(1, "FeatureMapSpriteGroup: Too many houses defined, skipping");
+				return;
+			}
+
+			hs->spritegroup = _cur_grffile->spritegroups[groupid];
+			hs->grffile = _cur_grffile;
+		}
+		return;
 	}
 
 	// FIXME: Tropicset contains things like:
@@ -2148,6 +2483,7 @@
 					break;
 				}
 
+				case GSF_TOWNHOUSE:
 				default:
 					switch (GB(id, 8, 8)) {
 						case 0xC4: /* Station class name */
@@ -2167,7 +2503,15 @@
 							}
 							break;
 
-						case 0xC9:
+						case 0xC9: { /* House name */
+							if (_cur_grffile->housespec == NULL || _cur_grffile->housespec[GB(id, 0, 8)] == NULL) {
+								grfmsg(1, "FeatureNewName: Attempt to name undefined house 0x%X, ignoring.", GB(id, 0, 8));
+							} else {
+								_cur_grffile->housespec[GB(id, 0, 8)]->building_name = AddGRFString(_cur_grffile->grfid, id, lang, new_scheme, name, STR_UNDEFINED);
+							}
+							break;
+						}
+
 						case 0xD0:
 						case 0xDC:
 							AddGRFString(_cur_grffile->grfid, id, lang, new_scheme, name, STR_UNDEFINED);
@@ -2182,7 +2526,6 @@
 #if 0
 				case GSF_CANAL :
 				case GSF_BRIDGE :
-				case GSF_TOWNHOUSE :
 					AddGRFString(_cur_spriteid, id, lang, name);
 					switch (GB(id, 8,8)) {
 						case 0xC9: /* House name */
@@ -3478,7 +3821,7 @@
 	                   |                                        (1 << 0x16)  // canals
 	                   |                                        (1 << 0x17)  // newstartyear
 	                   |                                        (0 << 0x18)  // freighttrains
-	                   |                                        (0 << 0x19)  // newhouses
+	                   |                                        (1 << 0x19)  // newhouses
 	                   |                                        (1 << 0x1A)  // newbridges
 	                   |                                        (0 << 0x1B)  // newtownnames
 	                   |                                        (0 << 0x1C)  // moreanimations
@@ -3550,6 +3893,20 @@
 	}
 }
 
+static void ResetCustomHouses()
+{
+	GRFFile *file;
+	uint i;
+
+	for (file = _first_grffile; file != NULL; file = file->next) {
+		if (file->housespec == NULL) continue;
+		for (i = 0; i < HOUSE_MAX; i++) free(file->housespec[i]);
+
+		free(file->housespec);
+		file->housespec = NULL;
+	}
+}
+
 static void ResetNewGRF()
 {
 	GRFFile *next;
@@ -3610,6 +3967,10 @@
 	/* Reset the curencies array */
 	ResetCurrencies();
 
+	/* Reset the house array */
+	ResetCustomHouses();
+	ResetHouses();
+
 	// Reset station classes
 	ResetStationClasses();
 	ResetCustomStations();
@@ -3635,6 +3996,7 @@
 	_traininfo_vehicle_pitch = 0;
 	_traininfo_vehicle_width = 29;
 	_have_2cc = false;
+	_have_newhouses = false;
 	_signal_base = 0;
 	_coast_base = 0;
 
@@ -3838,6 +4200,41 @@
 	}
 }
 
+/** Add all new houses to the house array. House properties can be set at any
+ * time in the GRF file, so we can only add a house spec to the house array
+ * after the file has finished loading. We also need to check the dates, due to
+ * the TTDPatch behaviour described below that we need to emulate. */
+static void FinaliseHouseArray()
+{
+	/* If there are no houses with start dates before 1930, then all houses
+	 * with start dates of 1930 have them reset to 0. This is in order to be
+	 * compatible with TTDPatch, where if no houses have start dates before
+	 * 1930 and the date is before 1930, the game pretends that this is 1930.
+	 * If there have been any houses defined with start dates before 1930 then
+	 * the dates are left alone. */
+	bool reset_dates = true;
+
+	for (GRFFile *file = _first_grffile; file != NULL; file = file->next) {
+		if (file->housespec == NULL) continue;
+
+		for (int i = 0; i < HOUSE_MAX; i++) {
+			HouseSpec *hs = file->housespec[i];
+			if (hs != NULL) {
+				SetHouseSpec(hs);
+				if (hs->min_date < 1930) reset_dates = false;
+			}
+		}
+	}
+
+	if (reset_dates) {
+		for (int i = NEW_HOUSE_OFFSET; i < HOUSE_MAX; i++) {
+			HouseSpec *hs = GetHouseSpecs(i);
+
+			if (hs->enabled && hs->min_date == 1930) hs->min_date = 0;
+		}
+	}
+}
+
 /* Here we perform initial decoding of some special sprites (as are they
  * described at http://www.ttdpatch.net/src/newgrf.txt, but this is only a very
  * partial implementation yet). */
@@ -4003,6 +4400,18 @@
 
 void InitDepotWindowBlockSizes();
 
+static void AfterLoadGRFs()
+{
+	/* Pre-calculate all refit masks after loading GRF files. */
+	CalculateRefitMasks();
+
+	/* Set the block size in the depot windows based on vehicle sprite sizes */
+	InitDepotWindowBlockSizes();
+
+	/* Add all new houses to the house array. */
+	FinaliseHouseArray();
+}
+
 void LoadNewGRF(uint load_index, uint file_index)
 {
 	InitializeGRFSpecial();
@@ -4033,9 +4442,6 @@
 		}
 	}
 
-	// Pre-calculate all refit masks after loading GRF files
-	CalculateRefitMasks();
-
-	/* Set the block size in the depot windows based on vehicle sprite sizes */
-	InitDepotWindowBlockSizes();
+	/* Call any functions that should be run after GRFs have been loaded. */
+	AfterLoadGRFs();
 }
--- a/src/newgrf.h	Mon Mar 19 12:38:16 2007 +0000
+++ b/src/newgrf.h	Mon Mar 19 12:49:55 2007 +0000
@@ -4,6 +4,7 @@
 #define NEWGRF_H
 
 #include "station.h"
+#include "town.h"
 #include "newgrf_config.h"
 #include "helpers.hpp"
 #include "cargotype.h"
@@ -56,6 +57,7 @@
 	uint sound_offset;
 
 	StationSpec **stations;
+	HouseSpec **housespec;
 
 	uint32 param[0x80];
 	uint param_end; /// one more than the highest set parameter
@@ -72,6 +74,7 @@
 extern SpriteID _signal_base;
 extern SpriteID _coast_base;
 extern bool _have_2cc;
+extern bool _have_newhouses;
 
 void LoadNewGRFFile(GRFConfig *config, uint file_index, GrfLoadingStage stage);
 void LoadNewGRF(uint load_index, uint file_index);
--- a/src/newgrf_callbacks.h	Mon Mar 19 12:38:16 2007 +0000
+++ b/src/newgrf_callbacks.h	Mon Mar 19 12:49:55 2007 +0000
@@ -37,10 +37,42 @@
 
 	CBID_TRAIN_ARTIC_ENGINE         = 0x16,
 
+	/* Called (if appropriate bit in callback mask is set) to determine whether
+	 * the house can be built on the specified tile. */
+	CBID_HOUSE_ALLOW_CONSTRUCTION   = 0x17,
+
 	CBID_VEHICLE_CARGO_SUFFIX       = 0x19,
 
+	/* Called (if appropriate bit in callback mask is set) to determine
+	 * the next animation frame. */
+	CBID_HOUSE_ANIMATION_NEXT_FRAME = 0x1A,
+
+	/* Called (if appropriate bit in callback mask is set) for periodically
+	 * starting or stopping the animation. */
+	CBID_HOUSE_ANIMATION_START_STOP = 0x1B,
+
+	/* Called (if appropriate bit in callback mask is set) whenever the
+	 * construction state of a house changes. */
+	CBID_CONSTRUCTION_STATE_CHANGE  = 0x1C,
+
 	CBID_TRAIN_ALLOW_WAGON_ATTACH   = 0x1D,
 
+	/* Called (if appropriate bit in callback mask is set) to determine the
+	 * colour of a town building. */
+	CBID_BUILDING_COLOUR            = 0x1E,
+
+	/* Called (if appropriate bit in callback mask is set) to decide how much
+	 * cargo a town building can accept. */
+	CBID_HOUSE_CARGO_ACCEPTANCE     = 0x1F, // not yet implemented
+
+	/* Called (if appropriate bit in callback mask is set) to indicate
+	 * how long the current animation frame should last. */
+	CBID_HOUSE_ANIMATION_SPEED      = 0x20,
+
+	/* Called (if appropriate bit in callback mask is set) periodically to
+	 * determine if a house should be destroyed. */
+	CBID_HOUSE_DESTRUCTION          = 0x21,
+
 	/* This callback is called from vehicle purchase lists. It returns a value to be
 	 * used as a custom string ID in the 0xD000 range. */
 	CBID_VEHICLE_ADDITIONAL_TEXT    = 0x23,
@@ -48,16 +80,28 @@
 	/* Called when building a station to customize the tile layout */
 	CBID_STATION_TILE_LAYOUT        = 0x24,
 
+	/* Called (if appropriate bit in callback mask is set) to determine which
+	 * cargoes a town building should accept. */
+	CBID_HOUSE_ACCEPT_CARGO         = 0x2A, // not yet implemented
+
 	/* Called to determine if a specific colour map should be used for a vehicle
 	 * instead of the default livery */
 	CBID_VEHICLE_COLOUR_MAPPING     = 0x2D,
 
+	/* Called (if appropriate bit in callback mask is set) to determine how much
+	 * cargo a town building produces. */
+	CBID_HOUSE_PRODUCE_CARGO        = 0x2E, // not yet implemented
+
 	/* Called when the player (or AI) tries to start or stop a vehicle. Mainly
 	 * used for preventing a vehicle from leaving the depot. */
 	CBID_VEHICLE_START_STOP_CHECK   = 0x31,
 
 	/* Called to play a special sound effect */
 	CBID_VEHICLE_SOUND_EFFECT       = 0x33,
+
+	/* Called (if appropriate bit in callback mask set) to determine whether a
+	 * town building can be destroyed. */
+	CBID_HOUSE_DENY_DESTRUCTION     = 0x143,
 };
 
 /**
@@ -84,6 +128,23 @@
 };
 
 /**
+ * Callback masks for houses.
+ */
+enum HouseCallbackMask {
+	CBM_HOUSE_ALLOW_CONSTRUCTION  = 0,
+	CBM_ANIMATION_NEXT_FRAME      = 1,
+	CBM_ANIMATION_START_STOP      = 2,
+	CBM_CONSTRUCTION_STATE_CHANGE = 3,
+	CBM_BUILDING_COLOUR           = 4,
+	CBM_CARGO_ACCEPTANCE          = 5,
+	CBM_ANIMATION_SPEED           = 6,
+	CBM_HOUSE_DESTRUCTION         = 7,
+	CBM_HOUSE_ACCEPT_CARGO        = 8,
+	CBM_HOUSE_PRODUCE_CARGO       = 9,
+	CBM_HOUSE_DENY_DESTRUCTION    = 10,
+};
+
+/**
  * Result of a failed callback.
  */
 enum {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/newgrf_house.cpp	Mon Mar 19 12:49:55 2007 +0000
@@ -0,0 +1,609 @@
+/* $Id$ */
+
+/** @file newgrf_house.cpp */
+
+#include "stdafx.h"
+#include "openttd.h"
+#include "functions.h"
+#include "variables.h"
+#include "debug.h"
+#include "viewport.h"
+#include "date.h"
+#include "town.h"
+#include "town_map.h"
+#include "sound.h"
+#include "sprite.h"
+#include "strings.h"
+#include "table/strings.h"
+#include "table/sprites.h"
+#include "table/town_land.h"
+#include "newgrf.h"
+#include "newgrf_house.h"
+#include "newgrf_spritegroup.h"
+#include "newgrf_callbacks.h"
+#include "newgrf_town.h"
+#include "newgrf_sound.h"
+
+static BuildingCounts    _building_counts;
+static HouseClassMapping _class_mapping[HOUSE_CLASS_MAX];
+HouseIDMapping _house_id_mapping[HOUSE_MAX];
+
+/* Since the house IDs defined by the GRF file don't necessarily correlate
+ * to those used by the game, the IDs used for overriding old houses must be
+ * translated when the house spec is set. */
+static uint16 _house_overrides[NEW_HOUSE_OFFSET];
+
+void AddHouseOverride(uint8 local_id, uint house_type)
+{
+	assert(house_type < NEW_HOUSE_OFFSET);
+	_house_overrides[house_type] = local_id;
+}
+
+void ResetHouseOverrides()
+{
+	for (int i = 0; i != lengthof(_house_overrides); i++) {
+		_house_overrides[i] = INVALID_HOUSE_ID;
+	}
+}
+
+static HouseID GetHouseID(byte grf_local_id, uint32 grfid)
+{
+	const HouseIDMapping *map;
+
+	for (HouseID house_id = NEW_HOUSE_OFFSET; house_id != lengthof(_house_id_mapping); house_id++) {
+		map = &_house_id_mapping[house_id];
+		if (map->house_id == grf_local_id && map->grfid == grfid) return house_id;
+	}
+	return INVALID_HOUSE_ID;
+}
+
+static HouseID AddHouseID(byte grf_local_id, uint32 grfid, byte substitute_id)
+{
+	HouseID house_id;
+	HouseIDMapping *map;
+
+	/* Look to see if this house has already been added. This is done
+	 * separately from the loop below in case a GRF has been deleted, and there
+	 * are any gaps in the array. */
+	house_id = GetHouseID(grf_local_id, grfid);
+	if (house_id != INVALID_HOUSE_ID) return house_id;
+
+	/* This house hasn't been defined before, so give it an ID now. */
+	for (house_id = NEW_HOUSE_OFFSET; house_id != lengthof(_house_id_mapping); house_id++) {
+		map = &_house_id_mapping[house_id];
+
+		if (map->house_id == 0 && map->grfid == 0) {
+			map->house_id      = grf_local_id;
+			map->grfid         = grfid;
+			map->substitute_id = substitute_id;
+			return house_id;
+		}
+	}
+
+	return INVALID_HOUSE_ID;
+}
+
+void SetHouseSpec(const HouseSpec *hs)
+{
+	HouseID house_id = AddHouseID(hs->local_id, hs->grffile->grfid, hs->substitute_id);
+
+	if (house_id == INVALID_HOUSE_ID) {
+		grfmsg(1, "SetHouseSpec: Too many houses allocated. Ignoring.");
+		return;
+	}
+
+	memcpy(&_house_specs[house_id], hs, sizeof(*hs));
+
+	/* Now add the overrides. */
+	for (int i = 0; i != lengthof(_house_overrides); i++) {
+		HouseSpec *overridden_hs = GetHouseSpecs(i);
+
+		if (_house_overrides[i] != hs->local_id) continue;
+
+		overridden_hs->override = house_id;
+		_house_overrides[i] = INVALID_HOUSE_ID;
+	}
+}
+
+void ResetHouseIDMapping()
+{
+	memset(&_house_id_mapping, 0, sizeof(_house_id_mapping));
+}
+
+void CheckHouseIDs()
+{
+	for (TileIndex t = 0; t < MapSize(); t++) {
+		HouseID house_id;
+
+		if (!IsTileType(t, MP_HOUSE)) continue;
+
+		house_id = GetHouseType(t);
+		if (!GetHouseSpecs(house_id)->enabled && house_id >= NEW_HOUSE_OFFSET) {
+			/* The specs for this type of house are not available any more, so
+			 * replace it with the substitute original house type. */
+			SetHouseType(t, _house_id_mapping[house_id].substitute_id);
+		}
+	}
+
+	InitializeBuildingCounts();
+	AfterLoadCountBuildings();
+
+}
+
+HouseClassID AllocateHouseClassID(byte grf_class_id, uint32 grfid)
+{
+	/* Start from 1 because 0 means that no class has been assigned. */
+	for (int i = 1; i != lengthof(_class_mapping); i++) {
+		HouseClassMapping *map = &_class_mapping[i];
+
+		if (map->class_id == grf_class_id && map->grfid == grfid) return (HouseClassID)i;
+
+		if (map->class_id == 0 && map->grfid == 0) {
+			map->class_id = grf_class_id;
+			map->grfid    = grfid;
+			return (HouseClassID)i;
+		}
+	}
+	return HOUSE_NO_CLASS;
+}
+
+void InitializeBuildingCounts()
+{
+	memset(&_building_counts, 0, sizeof(_building_counts));
+}
+
+/**
+ * IncreaseBuildingCount()
+ * Increase the count of a building when it has been added by a town.
+ * @param t The town that the building is being built in
+ * @param house_id The id of the house being added
+ */
+void IncreaseBuildingCount(Town *t, HouseID house_id)
+{
+	HouseClassID class_id = GetHouseSpecs(house_id)->class_id;
+
+	if (!_have_newhouses) return;
+
+	/* If there are 255 buildings of this type in this town, there are also
+	 * at least that many houses of the same class in the town, and
+	 * therefore on the map as well. */
+	if (t->building_counts.id_count[house_id] == 255) return;
+
+	t->building_counts.id_count[house_id]++;
+	if (_building_counts.id_count[house_id] < 255) _building_counts.id_count[house_id]++;
+
+	/* Similarly, if there are 255 houses of this class in this town, there
+	 * must be at least that number on the map too. */
+	if (class_id == HOUSE_NO_CLASS || t->building_counts.class_count[class_id] == 255) return;
+
+	t->building_counts.class_count[class_id]++;
+	if (_building_counts.class_count[class_id] < 255) _building_counts.class_count[class_id]++;
+}
+
+/**
+ * DecreaseBuildingCount()
+ * Decrease the number of a building when it is deleted.
+ * @param t The town that the building was built in
+ * @param house_id The id of the house being removed
+ */
+void DecreaseBuildingCount(Town *t, HouseID house_id)
+{
+	HouseClassID class_id = GetHouseSpecs(house_id)->class_id;
+
+	if (!_have_newhouses) return;
+
+	if (t->building_counts.id_count[house_id] > 0) t->building_counts.id_count[house_id]--;
+	if (_building_counts.id_count[house_id] > 0)   _building_counts.id_count[house_id]--;
+
+	if (class_id == HOUSE_NO_CLASS) return;
+
+	if (t->building_counts.class_count[class_id] > 0) t->building_counts.class_count[class_id]--;
+	if (_building_counts.class_count[class_id] > 0)   _building_counts.class_count[class_id]--;
+}
+
+/**
+ * AfterLoadCountBuildings()
+ *
+ * After a savegame has been loaded, count the number of buildings on the map.
+ */
+void AfterLoadCountBuildings()
+{
+	if (!_have_newhouses) return;
+
+	for (TileIndex t = 0; t < MapSize(); t++) {
+		if (!IsTileType(t, MP_HOUSE)) continue;
+		IncreaseBuildingCount(GetTownByTile(t), GetHouseType(t));
+	}
+}
+
+
+static uint32 HouseGetRandomBits(const ResolverObject *object)
+{
+	const TileIndex tile = object->u.house.tile;
+	return (tile == INVALID_TILE || !IsTileType(tile, MP_HOUSE)) ? 0 : GetHouseRandomBits(tile);
+}
+
+static uint32 HouseGetTriggers(const ResolverObject *object)
+{
+	const TileIndex tile = object->u.house.tile;
+	return (tile == INVALID_TILE || !IsTileType(tile, MP_HOUSE)) ? 0 : GetHouseTriggers(tile);
+}
+
+static void HouseSetTriggers(const ResolverObject *object, int triggers)
+{
+	const TileIndex tile = object->u.house.tile;
+	if (IsTileType(tile, MP_HOUSE)) SetHouseTriggers(tile, triggers);
+}
+
+static uint32 GetNumHouses(HouseID house_id, const Town *town)
+{
+	uint8 map_id_count, town_id_count, map_class_count, town_class_count;
+	HouseClassID class_id = GetHouseSpecs(house_id)->class_id;
+
+	map_id_count     = _building_counts.id_count[house_id];
+	map_class_count  = _building_counts.class_count[class_id];
+	town_id_count    = town->building_counts.id_count[house_id];
+	town_class_count = town->building_counts.class_count[class_id];
+
+	return map_class_count << 24 | town_class_count << 16 | map_id_count << 8 | town_id_count;
+}
+
+static uint32 GetTerrainType(TileIndex tile)
+{
+	switch (_opt.landscape) {
+		case LT_DESERT: return GetTropicZone(tile) == TROPICZONE_DESERT ? 1 : 2;
+		case LT_HILLY:  return GetTileZ(tile) >= _opt.snow_line ? 4 : 0;
+		default:        return 0;
+	}
+}
+
+static uint32 GetGRFParameter(HouseID house_id, byte parameter)
+{
+	const HouseSpec *hs = GetHouseSpecs(house_id);
+	const GRFFile *file = hs->grffile;
+
+	if (parameter >= file->param_end) return 0;
+	return file->param[parameter];
+}
+
+/**
+ * HouseGetVariable():
+ *
+ * Used by the resolver to get values for feature 07 deterministic spritegroups.
+ */
+static uint32 HouseGetVariable(const ResolverObject *object, byte variable, byte parameter, bool *available)
+{
+	const Town *town = object->u.house.town;
+	TileIndex tile   = object->u.house.tile;
+	HouseID house_id = object->u.house.house_id;
+
+	if (object->scope == VSG_SCOPE_PARENT) {
+		return TownGetVariable(variable, parameter, available, town);
+	}
+
+	switch (variable) {
+		/* Construction stage. */
+		case 0x40: return (IsTileType(tile, MP_HOUSE) ? GetHouseBuildingStage(tile) : 0) | OriginalTileRandomiser(TileX(tile), TileY(tile)) << 2;
+
+		/* Building age. */
+		case 0x41: return clamp(_cur_year - GetHouseConstructionYear(tile), 0, 0xFF);
+
+		/* Town zone */
+		case 0x42: return GetTownRadiusGroup(town, tile);
+
+		/* Terrain type */
+		case 0x43: return GetTerrainType(tile);
+
+		/* Number of this type of building on the map. */
+		case 0x44: return GetNumHouses(house_id, town);
+
+		/* Whether the town is being created or just expanded. */
+		case 0x45: return _generating_world ? 1 : 0;
+
+		/* Current animation frame. */
+		case 0x46: return IsTileType(tile, MP_HOUSE) ? GetHouseAnimationFrame(tile) : 0;
+
+
+		/* Building counts for old houses with id = parameter. */
+		case 0x60: return GetNumHouses(parameter, town);
+
+		/* Building counts for new houses with id = parameter. */
+		case 0x61: {
+			const HouseSpec *hs = GetHouseSpecs(house_id);
+			if (hs->grffile == NULL) return 0;
+
+			HouseID new_house = GetHouseID(parameter, hs->grffile->grfid);
+			return new_house == INVALID_HOUSE_ID ? 0 : GetNumHouses(new_house, town);
+		}
+
+		/* Land info for nearby tiles. */
+		case 0x62: {
+			int8 x = GB(parameter, 0, 4);
+			int8 y = GB(parameter, 4, 4);
+			byte tile_type;
+
+			if (x >= 8) x -= 16;
+			if (y >= 8) y -= 16;
+
+			tile += TileDiffXY(x, y);
+
+			tile_type = GetTerrainType(tile) << 2 | (IsTileType(tile, MP_WATER) ? 1 : 0) << 1;
+
+			return GetTileType(tile) << 24 | (TileHeight(tile) * 8) << 16 | tile_type << 8 | GetTileSlope(tile, NULL);
+		}
+
+		/* Read GRF parameter */
+		case 0x7F: return GetGRFParameter(object->u.house.house_id, parameter);
+	}
+
+	DEBUG(grf, 1, "Unhandled house property 0x%X", variable);
+
+	*available = false;
+	return UINT_MAX;
+}
+
+static const SpriteGroup *HouseResolveReal(const ResolverObject *object, const SpriteGroup *group)
+{
+	/* Houses do not have 'real' groups */
+	return NULL;
+}
+
+/**
+ * NewHouseResolver():
+ *
+ * Returns a resolver object to be used with feature 07 spritegroups.
+ */
+static void NewHouseResolver(ResolverObject *res, HouseID house_id, TileIndex tile, Town *town)
+{
+	res->GetRandomBits = HouseGetRandomBits;
+	res->GetTriggers   = HouseGetTriggers;
+	res->SetTriggers   = HouseSetTriggers;
+	res->GetVariable   = HouseGetVariable;
+	res->ResolveReal   = HouseResolveReal;
+
+	res->u.house.tile     = tile;
+	res->u.house.town     = town;
+	res->u.house.house_id = house_id;
+
+	res->callback        = 0;
+	res->callback_param1 = 0;
+	res->callback_param2 = 0;
+	res->last_value      = 0;
+	res->trigger         = 0;
+	res->reseed          = 0;
+}
+
+uint16 GetHouseCallback(uint16 callback, uint32 param1, HouseID house_id, Town *town, TileIndex tile)
+{
+	ResolverObject object;
+	const SpriteGroup *group;
+
+	NewHouseResolver(&object, house_id, tile, town);
+	object.callback = callback;
+	object.callback_param1 = param1;
+	object.callback_param2 = 0;
+
+	group = Resolve(GetHouseSpecs(house_id)->spritegroup, &object);
+	if (group == NULL || group->type != SGT_CALLBACK) return CALLBACK_FAILED;
+
+	return group->g.callback.result;
+}
+
+void DrawTileLayout(const TileInfo *ti, const SpriteGroup *group, byte stage, HouseID house_id)
+{
+	const DrawTileSprites *dts = group->g.layout.dts;
+	const DrawTileSeqStruct *dtss;
+
+	SpriteID image = dts->ground_sprite;
+	SpriteID pal   = dts->ground_pal;
+
+	if (GB(image, 0, SPRITE_WIDTH) != 0) DrawGroundSprite(image, pal);
+
+	foreach_draw_tile_seq(dtss, dts->seq) {
+		if (GB(dtss->image, 0, SPRITE_WIDTH) == 0) continue;
+
+		image = dtss->image + stage;
+		pal   = dtss->pal;
+
+		if (!HASBIT(image, SPRITE_MODIFIER_OPAQUE) && ((_display_opt & DO_TRANS_BUILDINGS))) {
+			SETBIT(image, PALETTE_MODIFIER_TRANSPARENT);
+			pal = PALETTE_TO_TRANSPARENT;
+		} else if (HASBIT(image, PALETTE_MODIFIER_COLOR)) {
+			if (pal == 0) {
+				const HouseSpec *hs = GetHouseSpecs(house_id);
+				if (HASBIT(hs->callback_mask, CBM_BUILDING_COLOUR)) {
+					uint16 callback = GetHouseCallback(CBID_BUILDING_COLOUR, 0, house_id, GetTownByTile(ti->tile), ti->tile);
+					if (callback != CALLBACK_FAILED) {
+						/* If bit 14 is set, we should use a 2cc colour map, else use the callback value. */
+						pal = HASBIT(callback, 14) ? GB(callback, 0, 8) + SPR_2CCMAP_BASE : callback;
+					}
+				} else {
+					pal = hs->random_colour[OriginalTileRandomiser(ti->x, ti->y)] + PALETTE_RECOLOR_START;
+				}
+			}
+		} else {
+			pal = PAL_NONE;
+		}
+
+		if ((byte)dtss->delta_z != 0x80) {
+			AddSortableSpriteToDraw(
+				image, pal,
+				ti->x + dtss->delta_x, ti->y + dtss->delta_y,
+				dtss->size_x, dtss->size_y,
+				dtss->size_z, ti->z + dtss->delta_z
+			);
+		} else {
+			AddChildSpriteScreen(image, pal, dtss->delta_x, dtss->delta_y);
+		}
+	}
+}
+
+void DrawNewHouseTile(TileInfo *ti, HouseID house_id)
+{
+	const HouseSpec *hs = GetHouseSpecs(house_id);
+	const SpriteGroup *group;
+	ResolverObject object;
+
+	if (ti->tileh != SLOPE_FLAT) DrawFoundation(ti, ti->tileh);
+
+	NewHouseResolver(&object, house_id, ti->tile, GetTownByTile(ti->tile));
+
+	group = Resolve(hs->spritegroup, &object);
+	if (group == NULL || group->type != SGT_TILELAYOUT) {
+		/* XXX: This is for debugging purposes really, and shouldn't stay. */
+		DrawGroundSprite(SPR_SHADOW_CELL, PAL_NONE);
+	} else {
+		/* Limit the building stage to the number of stages supplied. */
+		byte stage = GetHouseBuildingStage(ti->tile);
+		stage = clamp(stage - 4 + group->g.layout.num_sprites, 0, group->g.layout.num_sprites - 1);
+		DrawTileLayout(ti, group, stage, house_id);
+	}
+}
+
+void AnimateNewHouseTile(TileIndex tile)
+{
+	const HouseSpec *hs = GetHouseSpecs(GetHouseType(tile));
+	byte animation_speed = hs->animation_speed;
+	bool frame_set_by_callback = false;
+
+	if (HASBIT(hs->callback_mask, CBM_ANIMATION_SPEED)) {
+		uint16 callback_res = GetHouseCallback(CBID_HOUSE_ANIMATION_SPEED, 0, GetHouseType(tile), GetTownByTile(tile), tile);
+		if (callback_res != CALLBACK_FAILED) animation_speed = clamp(callback_res & 0xFF, 2, 16);
+	}
+
+	/* An animation speed of 2 means the animation frame changes 4 ticks, and
+	 * increasing this value by one doubles the wait. 2 is the minimum value
+	 * allowed for animation_speed, which corresponds to 120ms, and 16 is the
+	 * maximum, corresponding to around 33 minutes. */
+	if (_tick_counter % (1 << animation_speed) != 0) return;
+
+	byte frame      = GetHouseAnimationFrame(tile);
+	byte num_frames = GB(hs->animation_frames, 0, 7);
+
+	if (HASBIT(hs->callback_mask, CBM_ANIMATION_NEXT_FRAME)) {
+		uint32 param = (hs->extra_flags & CALLBACK_1A_RANDOM_BITS) ? Random() : 0;
+		uint16 callback_res = GetHouseCallback(CBID_HOUSE_ANIMATION_NEXT_FRAME, param, GetHouseType(tile), GetTownByTile(tile), tile);
+
+		if (callback_res != CALLBACK_FAILED) {
+			frame_set_by_callback = true;
+
+			switch (callback_res & 0xFF) {
+				case 0xFF:
+					DeleteAnimatedTile(tile);
+					break;
+				case 0xFE:
+					/* Carry on as normal. */
+					frame_set_by_callback = false;
+					break;
+				default:
+					frame = callback_res & 0xFF;
+					break;
+			}
+
+			/* If the lower 7 bits of the upper byte of the callback
+			 * result are not empty, it is a sound effect. */
+			if (GB(callback_res, 8, 7) != 0) PlayHouseSound(GB(callback_res, 8, 7), tile);
+		}
+	}
+
+	if (!frame_set_by_callback) {
+		if (frame < num_frames) {
+			frame++;
+		} else if (frame == num_frames && HASBIT(hs->animation_frames, 7)) {
+			/* This animation loops, so start again from the beginning */
+			frame = 0;
+		} else {
+			/* This animation doesn't loop, so stay here */
+			DeleteAnimatedTile(tile);
+		}
+	}
+
+	SetHouseAnimationFrame(tile, frame);
+	MarkTileDirtyByTile(tile);
+}
+
+void ChangeHouseAnimationFrame(TileIndex tile, uint16 callback_result)
+{
+	switch (callback_result & 0xFF) {
+		case 0xFD: /* Do nothing. */         break;
+		case 0xFE: AddAnimatedTile(tile);    break;
+		case 0xFF: DeleteAnimatedTile(tile); break;
+		default:
+			SetHouseAnimationFrame(tile, callback_result & 0xFF);
+			AddAnimatedTile(tile);
+			break;
+	}
+	/* If the lower 7 bits of the upper byte of the callback
+	 * result are not empty, it is a sound effect. */
+	if (GB(callback_result, 8, 7) != 0) PlayHouseSound(GB(callback_result, 8, 7), tile);
+}
+
+bool CanDeleteHouse(TileIndex tile)
+{
+	const HouseSpec *hs = GetHouseSpecs(GetHouseType(tile));
+
+	/* Human players are always allowed to remove buildings, as is water and
+	 * anyone using the scenario editor. */
+	if ((IsValidPlayer(_current_player) && IsHumanPlayer(_current_player))
+			|| _current_player == OWNER_WATER || _current_player == OWNER_NONE) return true;
+
+	if (HASBIT(hs->callback_mask, CBM_HOUSE_DENY_DESTRUCTION)) {
+		uint16 callback_res = GetHouseCallback(CBID_HOUSE_DENY_DESTRUCTION, 0, GetHouseType(tile), GetTownByTile(tile), tile);
+		return (callback_res == CALLBACK_FAILED || callback_res == 0);
+	} else {
+		return !(hs->extra_flags & BUILDING_IS_PROTECTED);
+	}
+}
+
+static void AnimationControl(TileIndex tile, uint16 random_bits)
+{
+	const HouseSpec *hs = GetHouseSpecs(GetHouseType(tile));
+
+	if (HASBIT(hs->callback_mask, CBM_ANIMATION_START_STOP)) {
+		uint32 param = (hs->extra_flags & SYNCHRONISED_CALLBACK_1B) ? (GB(Random(), 0, 16) | random_bits << 16) : Random();
+		uint16 callback_res = GetHouseCallback(CBID_HOUSE_ANIMATION_START_STOP, param, GetHouseType(tile), GetTownByTile(tile), tile);
+
+		if (callback_res != CALLBACK_FAILED) ChangeHouseAnimationFrame(tile, callback_res);
+	}
+}
+
+bool NewHouseTileLoop(TileIndex tile)
+{
+	const HouseSpec *hs = GetHouseSpecs(GetHouseType(tile));
+
+	if (GetHouseProcessingTime(tile) > 0) {
+		DecHouseProcessingTime(tile);
+		return true;
+	}
+
+	/* @todo: Magic with triggers goes here.  Got to implement that, one day. .. */
+
+	if (HASBIT(hs->callback_mask, CBM_ANIMATION_START_STOP)) {
+		/* If this house is marked as having a synchronised callback, all the
+		 * tiles will have the callback called at once, rather than when the
+		 * tile loop reaches them. This should only be enabled for the northern
+		 * tile, or strange things will happen (here, and in TTDPatch). */
+		if (hs->extra_flags & SYNCHRONISED_CALLBACK_1B) {
+			uint16 random = GB(Random(), 0, 16);
+
+			if (hs->building_flags & BUILDING_HAS_1_TILE)  AnimationControl(tile, random);
+			if (hs->building_flags & BUILDING_2_TILES_Y)   AnimationControl(TILE_ADDXY(tile, 0, 1), random);
+			if (hs->building_flags & BUILDING_2_TILES_X)   AnimationControl(TILE_ADDXY(tile, 1, 0), random);
+			if (hs->building_flags & BUILDING_HAS_4_TILES) AnimationControl(TILE_ADDXY(tile, 1, 1), random);
+		} else {
+			AnimationControl(tile, 0);
+		}
+	}
+
+	/* Check callback 21, which determines if a house should be destroyed. */
+	if (HASBIT(hs->callback_mask, CBM_HOUSE_DESTRUCTION)) {
+		uint16 callback_res = GetHouseCallback(CBID_HOUSE_DESTRUCTION, 0, GetHouseType(tile), GetTownByTile(tile), tile);
+		if (callback_res != CALLBACK_FAILED && callback_res > 0) {
+			ClearTownHouse(GetTownByTile(tile), tile);
+			return false;
+		}
+	}
+
+	SetHouseProcessingTime(tile, hs->processing_time);
+	return true;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/newgrf_house.h	Mon Mar 19 12:49:55 2007 +0000
@@ -0,0 +1,71 @@
+/* $Id$ */
+
+/** @file newgrf_house.h */
+
+#ifndef NEWGRF_HOUSE_H
+#define NEWGRF_HOUSE_H
+
+#include "town.h"
+
+/**
+ * Maps a house id stored on the map to a GRF file.
+ * House IDs are stored on the map, so there needs to be a way to tie them to
+ * GRF files. An array of HouseIDMapping structs is saved with the savegame so
+ * that house GRFs can be loaded in a different order, or removed safely. The
+ * index in the array is the house ID stored on the map.
+ *
+ * The substitute ID is the ID of an original house that should be used instead
+ * if the GRF containing the new house is not available.
+ */
+struct HouseIDMapping {
+	uint32 grfid;          ///< The GRF ID of the file this house belongs to
+	uint8  house_id;       ///< The house ID within the GRF file
+	uint8  substitute_id;  ///< The (original) house ID to use if this GRF is not available
+};
+
+/**
+ * Makes class IDs unique to each GRF file.
+ * Houses can be assigned class IDs which are only comparable within the GRF
+ * file they were defined in. This mapping ensures that if two houses have the
+ * same class as defined by the GRF file, the classes are different within the
+ * game. An array of HouseClassMapping structs is created, and the array index
+ * of the struct that matches both the GRF ID and the class ID is the class ID
+ * used in the game.
+ *
+ * Although similar to the HouseIDMapping struct above, this serves a different
+ * purpose. Since the class ID is not saved anywhere, this mapping does not
+ * need to be persistent; it just needs to keep class ids unique.
+ */
+struct HouseClassMapping {
+	uint32 grfid;     ////< The GRF ID of the file this class belongs to
+	uint8  class_id;  ////< The class id within the grf file
+};
+
+extern HouseIDMapping _house_id_mapping[HOUSE_MAX]; ///< Declared in newgrf_house.cpp
+
+void AddHouseOverride(uint8 local_id, uint house_type);
+void ResetHouseOverrides();
+
+void SetHouseSpec(const HouseSpec *hs);
+
+void CheckHouseIDs();
+void ResetHouseIDMapping();
+
+HouseClassID AllocateHouseClassID(byte grf_class_id, uint32 grfid);
+
+void InitializeBuildingCounts();
+void IncreaseBuildingCount(Town *t, HouseID house_id);
+void DecreaseBuildingCount(Town *t, HouseID house_id);
+void AfterLoadCountBuildings();
+
+void DrawNewHouseTile(TileInfo *ti, HouseID house_id);
+void AnimateNewHouseTile(TileIndex tile);
+void ChangeHouseAnimationFrame(TileIndex tile, uint16 callback_result);
+
+uint16 GetHouseCallback(uint16 callback, uint32 param1, HouseID house_id, Town *town, TileIndex tile);
+
+bool CanDeleteHouse(TileIndex tile);
+
+bool NewHouseTileLoop(TileIndex tile);
+
+#endif /* NEWGRF_HOUSE_H */
--- a/src/newgrf_sound.cpp	Mon Mar 19 12:38:16 2007 +0000
+++ b/src/newgrf_sound.cpp	Mon Mar 19 12:49:55 2007 +0000
@@ -66,3 +66,12 @@
 	if (callback < GetNumSounds()) SndPlayVehicleFx((SoundFx)callback, v);
 	return true;
 }
+
+bool PlayHouseSound(uint16 sound_id, TileIndex tile)
+{
+	if (sound_id < GetNumOriginalSounds()) {
+		SndPlayTileFx((SoundFx)sound_id, tile);
+		return true;
+	}
+	return false;
+}
--- a/src/newgrf_sound.h	Mon Mar 19 12:38:16 2007 +0000
+++ b/src/newgrf_sound.h	Mon Mar 19 12:49:55 2007 +0000
@@ -21,5 +21,6 @@
 FileEntry *GetSound(uint index);
 uint GetNumSounds();
 bool PlayVehicleSound(const Vehicle *v, VehicleSoundEvent event);
+bool PlayHouseSound(uint16 sound_id, TileIndex tile);
 
 #endif /* NEWGRF_SOUND_H */
--- a/src/newgrf_spritegroup.cpp	Mon Mar 19 12:38:16 2007 +0000
+++ b/src/newgrf_spritegroup.cpp	Mon Mar 19 12:49:55 2007 +0000
@@ -8,6 +8,7 @@
 #include "newgrf_callbacks.h"
 #include "newgrf_spritegroup.h"
 #include "date.h"
+#include "sprite.h"
 
 static void SpriteGroupPoolCleanBlock(uint start_item, uint end_item);
 
@@ -33,6 +34,11 @@
 			free((SpriteGroup**)group->g.random.groups);
 			break;
 
+		case SGT_TILELAYOUT:
+			free((void*)group->g.layout.dts->seq);
+			free(group->g.layout.dts);
+			break;
+
 		default:
 			break;
 	}
--- a/src/newgrf_spritegroup.h	Mon Mar 19 12:38:16 2007 +0000
+++ b/src/newgrf_spritegroup.h	Mon Mar 19 12:49:55 2007 +0000
@@ -3,6 +3,7 @@
 #ifndef NEWGRF_SPRITEGROUP_H
 #define NEWGRF_SPRITEGROUP_H
 
+#include "town.h"
 
 struct SpriteGroup;
 
@@ -128,6 +129,11 @@
 	byte num_sprites;
 };
 
+struct TileLayoutSpriteGroup {
+	byte num_sprites; /* Number of sprites in the spriteset, used for loading stages */
+	struct DrawTileSprites *dts;
+};
+
 /* List of different sprite group types */
 enum SpriteGroupType {
 	SGT_INVALID,
@@ -136,6 +142,7 @@
 	SGT_RANDOMIZED,
 	SGT_CALLBACK,
 	SGT_RESULT,
+	SGT_TILELAYOUT,
 };
 
 /* Common wrapper for all the different sprite group types */
@@ -148,6 +155,7 @@
 		RandomizedSpriteGroup random;
 		CallbackResultSpriteGroup callback;
 		ResultSpriteGroup result;
+		TileLayoutSpriteGroup layout;
 	} g;
 };
 
@@ -180,6 +188,11 @@
 			const struct StationSpec *statspec;
 			CargoID cargo_type;
 		} station;
+		struct {
+			TileIndex tile;
+			Town *town;
+			HouseID house_id;
+		} house;
 	} u;
 
 	uint32 (*GetRandomBits)(const struct ResolverObject*);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/newgrf_town.cpp	Mon Mar 19 12:49:55 2007 +0000
@@ -0,0 +1,91 @@
+/* $Id$ */
+
+/** @file newgrf_town.cpp */
+
+#include "stdafx.h"
+#include "openttd.h"
+#include "debug.h"
+#include "functions.h"
+#include "town.h"
+
+/** This function implements the town variables that newGRF defines.
+ * @param variable that is queried
+ * @param parameter unused
+ * @param available will return false if ever the variable asked for does not exist
+ * @param t is of course the town we are inquiring
+ * @return the value stored in the corresponding variable*/
+uint32 TownGetVariable(byte variable, byte parameter, bool *available, const Town *t)
+{
+	switch (variable) {
+		/* Larger towns */
+		case 0x40: return 1;
+
+		/* Town index */
+		case 0x41: return t->index;
+
+		/* Town properties */
+		case 0x80: return t->xy;
+		case 0x81: return GB(t->xy, 8, 8);
+		case 0x82: return t->population;
+		case 0x83: return GB(t->population, 8, 8);
+		case 0x8A: return t->grow_counter;
+		case 0x92: return t->flags12;  // In original game, 0x92 and 0x93 are really one word. Since flags12 is a byte, this is to adjust
+		case 0x93: return 0;
+		case 0x94: return t->radius[0];
+		case 0x95: return GB(t->radius[0], 8, 8);
+		case 0x96: return t->radius[1];
+		case 0x97: return GB(t->radius[1], 8, 8);
+		case 0x98: return t->radius[2];
+		case 0x99: return GB(t->radius[2], 8, 8);
+		case 0x9A: return t->radius[3];
+		case 0x9B: return GB(t->radius[3], 8, 8);
+		case 0x9C: return t->radius[4];
+		case 0x9D: return GB(t->radius[4], 8, 8);
+		case 0x9E: return t->ratings[0];
+		case 0x9F: return t->ratings[1];
+		case 0xA0: return t->ratings[2];
+		case 0xA1: return t->ratings[3];
+		case 0xA2: return t->ratings[4];
+		case 0xA3: return t->ratings[5];
+		case 0xA4: return t->ratings[6];
+		case 0xA5: return t->ratings[7];
+		case 0xA6: return t->ratings[8];
+		case 0xAE: return t->have_ratings;
+		case 0xB2: return t->statues;
+		case 0xB6: return t->num_houses;
+		case 0xB9: return t->growth_rate;
+		case 0xBA: return t->new_max_pass;
+		case 0xBB: return GB(t->new_max_pass, 8, 8);
+		case 0xBC: return t->new_max_mail;
+		case 0xBD: return GB(t->new_max_mail, 8, 8);
+		case 0xBE: return t->new_act_pass;
+		case 0xBF: return GB(t->new_act_pass, 8, 8);
+		case 0xC0: return t->new_act_mail;
+		case 0xC1: return GB(t->new_act_mail, 8, 8);
+		case 0xC2: return t->max_pass;
+		case 0xC3: return GB(t->max_pass, 8, 8);
+		case 0xC4: return t->max_mail;
+		case 0xC5: return GB(t->max_mail, 8, 8);
+		case 0xC6: return t->act_pass;
+		case 0xC7: return GB(t->act_pass, 8, 8);
+		case 0xC8: return t->act_mail;
+		case 0xC9: return GB(t->act_mail, 8, 8);
+		case 0xCA: return t->pct_pass_transported;
+		case 0xCB: return t->pct_mail_transported;
+		case 0xCC: return t->new_act_food;
+		case 0xCD: return GB(t->new_act_food, 8, 8);
+		case 0xCE: return t->new_act_water;
+		case 0xCF: return GB(t->new_act_water, 8, 8);
+		case 0xD0: return t->act_food;
+		case 0xD1: return GB(t->act_food, 8, 8);
+		case 0xD2: return t->act_water;
+		case 0xD3: return GB(t->act_water, 8, 8);
+		case 0xD4: return t->road_build_months;
+		case 0xD5: return t->fund_buildings_months;
+	}
+
+	DEBUG(grf, 1, "Unhandled town property 0x%X", variable);
+
+	*available = false;
+	return (uint32)-1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/newgrf_town.h	Mon Mar 19 12:49:55 2007 +0000
@@ -0,0 +1,13 @@
+/* $Id$ */
+
+/** @file newgrf_town.h */
+
+#ifndef NEWGRF_TOWN_H
+#define NEWGRF_TOWN_H
+
+/* Currently there is no direct town resolver; we only need to get town
+ * variable results from inside stations, house tiles and industry tiles. */
+
+uint32 TownGetVariable(byte variable, byte parameter, bool *available, const Town *t);
+
+#endif /* NEWGRF_TOWN_H */
--- a/src/openttd.cpp	Mon Mar 19 12:38:16 2007 +0000
+++ b/src/openttd.cpp	Mon Mar 19 12:49:55 2007 +0000
@@ -56,6 +56,7 @@
 #include "clear_map.h"
 #include "fontcache.h"
 #include "newgrf_config.h"
+#include "newgrf_house.h"
 #include "player_face.h"
 
 #include "bridge_map.h"
@@ -677,6 +678,7 @@
 	_game_mode = GM_NORMAL;
 
 	ResetGRFConfig(true);
+	ResetHouseIDMapping();
 
 	GenerateWorldSetCallback(&MakeNewGameDone);
 	GenerateWorld(from_heightmap ? GW_HEIGHTMAP : GW_NEWGAME, 1 << _patches.map_x, 1 << _patches.map_y);
@@ -1756,6 +1758,47 @@
 	/* do the same as when elrails were enabled/disabled manually just now */
 	SettingsDisableElrail(_patches.disable_elrails);
 
+	/* From version 53, the map array was changed for house tiles to allow
+	 * space for newhouses grf features. A new byte, m7, was also added. */
+	if (CheckSavegameVersion(53)) {
+		for (TileIndex t = 0; t < map_size; t++) {
+			_me[t].m7 = 0;
+
+			if (IsTileType(t, MP_HOUSE)) {
+				if (GB(_m[t].m3, 6, 2) != TOWN_HOUSE_COMPLETED) {
+					/* Move the construction stage from m3[7..6] to m5[5..4].
+					 * The construction counter does not have to move. */
+					SB(_m[t].m5, 3, 2, GB(_m[t].m3, 6, 2));
+					SB(_m[t].m3, 6, 2, 0);
+
+					/* The "house is completed" bit is now in m6[2]. */
+					SetHouseCompleted(t, false);
+				} else {
+					/* The "lift has destination" bit has been moved from
+					 * m5[7] to m7[0]. */
+					SB(_me[t].m7, 0, 1, HASBIT(_m[t].m5, 7));
+					CLRBIT(_m[t].m5, 7);
+
+					/* The "lift is moving" bit has been removed, as it does
+					 * the same job as the "lift has destination" bit. */
+					CLRBIT(_m[t].m1, 7);
+
+					/* The position of the lift goes from m1[7..0] to m6[7..2],
+					 * making m1 totally free, now. The lift position does not
+					 * have to be a full byte since the maximum value is 36. */
+					SetLiftPosition(t, GB(_m[t].m1, 0, 6 ));
+
+					_m[t].m1 = 0;
+					_m[t].m3 = 0;
+					SetHouseCompleted(t, true);
+				}
+			}
+		}
+	}
+
+	/* Count the buildings after updating the map array. */
+	AfterLoadCountBuildings();
+
 	if (CheckSavegameVersion(43)) {
 		for (TileIndex t = 0; t < map_size; t++) {
 			if (IsTileType(t, MP_INDUSTRY)) {
@@ -1886,6 +1929,8 @@
 	/* update station and waypoint graphics */
 	AfterLoadWaypoints();
 	AfterLoadStations();
+	/* check that house ids are still valid */
+	CheckHouseIDs();
 	/* redraw the whole screen */
 	MarkWholeScreenDirty();
 }
--- a/src/saveload.cpp	Mon Mar 19 12:38:16 2007 +0000
+++ b/src/saveload.cpp	Mon Mar 19 12:49:55 2007 +0000
@@ -28,7 +28,7 @@
 #include "variables.h"
 #include <setjmp.h>
 
-extern const uint16 SAVEGAME_VERSION = 52;
+extern const uint16 SAVEGAME_VERSION = 53;
 uint16 _sl_version;       ///< the major savegame version identifier
 byte   _sl_minor_version; ///< the minor savegame version, DO NOT USE!
 
--- a/src/table/sprites.h	Mon Mar 19 12:38:16 2007 +0000
+++ b/src/table/sprites.h	Mon Mar 19 12:49:55 2007 +0000
@@ -35,7 +35,6 @@
  * @todo Split the "Sprites" enum into smaller chunks and document them
  */
 
-
 enum Sprites {
 	SPR_SELECT_TILE  = 752,
 	SPR_DOT          = 774, // corner marker for lower/raise land
@@ -1324,6 +1323,7 @@
  */
 enum Modifiers {
 	SPRITE_MODIFIER_USE_OFFSET    = OFFSET_BIT,
+	SPRITE_MODIFIER_OPAQUE        = OFFSET_BIT,
 	///when a sprite is to be displayed transparently, this bit needs to be set.
 	PALETTE_MODIFIER_TRANSPARENT  = TRANSPARENT_BIT,
 	///this bit is set when a recoloring process is in action
@@ -1418,6 +1418,5 @@
 	PALETTE_59E                 = 0x59E,
 	PALETTE_59F                 = 0x59F,
 };
-#undef PALETTE_RECOLOR_SPRITE
 
 #endif /* SPRITES_H */
--- a/src/table/town_land.h	Mon Mar 19 12:38:16 2007 +0000
+++ b/src/table/town_land.h	Mon Mar 19 12:49:55 2007 +0000
@@ -2,17 +2,6 @@
 
 /** @file town_land.h */
 
-enum {
-	HOUSE_TEMP_CHURCH    = 0x03,
-	HOUSE_STADIUM        = 0x14,
-	HOUSE_MODERN_STADIUM = 0x20,
-	HOUSE_ARCT_CHURCH    = 0x3c,
-	HOUSE_SNOW_CHURCH    = 0x3d,
-	HOUSE_TROP_CHURCH    = 0x53,
-	HOUSE_TOY_CHURCH     = 0x5b,
-
-	HOUSE_MAX            = 110
-};
 
 /** Writes the data into the Town Tile Drawing Struct
  * @param s1 The first sprite of the building, mostly the ground sprite
@@ -1790,437 +1779,372 @@
 	M(0x1244, PAL_NONE, 0x125a, PAL_NONE,  0,  0, 16, 16,  50, 0),
 };
 #undef M
-// 4 variants * 4 build stages
-assert_compile(lengthof(_town_draw_tile_data) == HOUSE_MAX * 4 * 4);
-
-
-static const StringID _town_tile_names[] = {
-	STR_200F_TALL_OFFICE_BLOCK,
-	STR_2010_OFFICE_BLOCK,
-	STR_2011_SMALL_BLOCK_OF_FLATS,
-	STR_2012_CHURCH,
-	STR_2013_LARGE_OFFICE_BLOCK,
-	STR_2013_LARGE_OFFICE_BLOCK,
-	STR_2014_TOWN_HOUSES,
-	STR_2015_HOTEL,
-	STR_2015_HOTEL,
-	STR_2016_STATUE,
-	STR_2017_FOUNTAIN,
-	STR_2018_PARK,
-	STR_2018_PARK,
-	STR_2019_OFFICE_BLOCK,
-	STR_201A_SHOPS_AND_OFFICES,
-	STR_201A_SHOPS_AND_OFFICES,
-	STR_201A_SHOPS_AND_OFFICES,
-	STR_201B_MODERN_OFFICE_BUILDING,
-	STR_201C_WAREHOUSE,
-	STR_201D_OFFICE_BLOCK,
-	STR_201E_STADIUM,
-	STR_201E_STADIUM,
-	STR_201E_STADIUM,
-	STR_201E_STADIUM,
-	STR_201F_OLD_HOUSES,
-	STR_2036_COTTAGES,
-	STR_2037_HOUSES,
-	STR_2038_FLATS,
-	STR_2039_TALL_OFFICE_BLOCK,
-	STR_203A_SHOPS_AND_OFFICES,
-	STR_203B_SHOPS_AND_OFFICES,
-	STR_203C_THEATER,
-	STR_203D_STADIUM,
-	STR_203D_STADIUM,
-	STR_203D_STADIUM,
-	STR_203D_STADIUM,
-	STR_203E_OFFICES,
-	STR_203F_HOUSES,
-	STR_203F_HOUSES,
-	STR_2040_CINEMA,
-	STR_2041_SHOPPING_MALL,
-	STR_2041_SHOPPING_MALL,
-	STR_2041_SHOPPING_MALL,
-	STR_2041_SHOPPING_MALL,
-	STR_2038_FLATS,
-	STR_2038_FLATS,
-	STR_203F_HOUSES,
-	STR_203F_HOUSES,
-	STR_203F_HOUSES,
-	STR_203F_HOUSES,
-	STR_200F_TALL_OFFICE_BLOCK,
-	STR_200F_TALL_OFFICE_BLOCK,
-	STR_200F_TALL_OFFICE_BLOCK,
-	STR_200F_TALL_OFFICE_BLOCK,
-	STR_200F_TALL_OFFICE_BLOCK,
-	STR_200F_TALL_OFFICE_BLOCK,
-	STR_203F_HOUSES,
-	STR_203F_HOUSES,
-	STR_201A_SHOPS_AND_OFFICES,
-	STR_201A_SHOPS_AND_OFFICES,
-	STR_2012_CHURCH,
-	STR_2012_CHURCH,
-	STR_203F_HOUSES,
-	STR_203F_HOUSES,
-	STR_201A_SHOPS_AND_OFFICES,
-	STR_201A_SHOPS_AND_OFFICES,
-	STR_2015_HOTEL,
-	STR_2015_HOTEL,
-	STR_2015_HOTEL,
-	STR_2015_HOTEL,
-	STR_201A_SHOPS_AND_OFFICES,
-	STR_201A_SHOPS_AND_OFFICES,
-	STR_200F_TALL_OFFICE_BLOCK,
-	STR_200F_TALL_OFFICE_BLOCK,
-	STR_200F_TALL_OFFICE_BLOCK,
-	STR_200F_TALL_OFFICE_BLOCK,
-	STR_200F_TALL_OFFICE_BLOCK,
-	STR_200F_TALL_OFFICE_BLOCK,
-	STR_203F_HOUSES,
-	STR_203F_HOUSES,
-	STR_203F_HOUSES,
-	STR_203F_HOUSES,
-	STR_2038_FLATS,
-	STR_2012_CHURCH,
-	STR_203F_HOUSES,
-	STR_2038_FLATS,
-	STR_2038_FLATS,
-	STR_200F_TALL_OFFICE_BLOCK,
-	STR_200F_TALL_OFFICE_BLOCK,
-	STR_2038_FLATS,
-	STR_200F_TALL_OFFICE_BLOCK,
-	STR_2012_CHURCH,
-	STR_203F_HOUSES,
-	STR_203F_HOUSES,
-	STR_203F_HOUSES,
-	STR_203F_HOUSES,
-	STR_203F_HOUSES,
-	STR_203F_HOUSES,
-	STR_200F_TALL_OFFICE_BLOCK,
-	STR_203F_HOUSES,
-	STR_203F_HOUSES,
-	STR_200F_TALL_OFFICE_BLOCK,
-	STR_2059_IGLOO,
-	STR_205A_TEPEES,
-	STR_201A_SHOPS_AND_OFFICES,
-	STR_201A_SHOPS_AND_OFFICES,
-	STR_200F_TALL_OFFICE_BLOCK,
-	STR_2016_STATUE,
-	STR_205B_TEAPOT_HOUSE,
-	STR_205C_PIGGY_BANK,
-};
-assert_compile(lengthof(_town_tile_names) == HOUSE_MAX);
-
-static const uint16 _housetype_flags[] = {
-	0x1010, 0x1018, 0x100E, 0x100F, 0x7010, 0x0810, 0x100F, 0x1014,
-	0x0000, 0x7018, 0x7010, 0x1004, 0x1008, 0x1018, 0x101C, 0x101C,
-	0x101C, 0x7010, 0x1010, 0x1010, 0x100F, 0x0000, 0x0000, 0x0000,
-	0x1003, 0x1001, 0x100F, 0x101C, 0x101C, 0x101C, 0x5014, 0x1018,
-	0x700F, 0x0000, 0x0000, 0x0000, 0x7018, 0x2003, 0x0803, 0x101C,
-	0x101E, 0x0000, 0x0000, 0x0000, 0x201C, 0x081C, 0x200F, 0x080F,
-	0x2007, 0x0807, 0x6018, 0x0818, 0x2018, 0x0818, 0x6018, 0x0818,
-	0x2001, 0x0801, 0x201E, 0x081E, 0x200F, 0x080F, 0x2007, 0x0807,
-	0x201C, 0x081C, 0x201C, 0x0000, 0x081C, 0x0000, 0x601C, 0x081C,
-	0x2018, 0x0818, 0x201C, 0x0000, 0x081C, 0x0000, 0x401E, 0x401E,
-	0x401E, 0x4001, 0x401C, 0x400E, 0x401E, 0x401C, 0x401C, 0x4018,
-	0x4000, 0x401C, 0x4018, 0x801F, 0x801F, 0x8003, 0x800F, 0x800F,
-	0x800F, 0x800F, 0x801C, 0x801F, 0x0000, 0x801C, 0x8001, 0x8001,
-	0x801C, 0x801C, 0x801C, 0x801C, 0x801F, 0x801F,
-};
-assert_compile(lengthof(_housetype_flags) == HOUSE_MAX);
-
-static const byte _housetype_extra_flags[] = {
-	 0,  0,  0,  0, 32, 32,  0,  8,
-	 0,  0,  0,  0,  0,  0,  0,  0,
-	 0,  0,  0,  0, 16,  0,  0,  0,
-	 0,  0,  0,  0,  0,  0,  0,  0,
-	16,  0,  0,  0,  0,  0,  0,  0,
-	16,  0,  0,  0,  0,  0,  0,  0,
-	 0,  0,  0,  0,  0,  0,  0,  0,
-	 0,  0,  0,  0,  0,  0,  0,  0,
-	 0,  0,  8,  0,  8,  0,  0,  0,
-	 0,  0,  4,  0,  4,  0,  0,  0,
-	 0,  0,  0,  0,  0,  0,  0,  4,
-	 0,  0,  0,  0,  0,  0,  0,  0,
-	 0,  0,  0,  8,  0,  0,  0,  0,
-	 0,  0,  0,  0,  0,  0,
-};
-assert_compile(lengthof(_housetype_extra_flags) == HOUSE_MAX);
-
-static const byte _housetype_population[] = {
-	187,  85,  40,   5, 220, 220,  30, 140,
-	  0,   0,   0,   0,   0, 150,  95,  95,
-	 95, 130,   6, 110,  65,   0,   0,   0,
-	 15,  12,  13, 100, 170, 100, 180,  35,
-	 65,   0,   0,   0, 140,  15,  15,  35,
-	180,   0,   0,   0,  80,  80,  16,  16,
-	 14,  14, 135, 135, 170, 170, 210, 210,
-	 10,  10,  25,  25,   6,   6,  17,  17,
-	 90,  90, 140,   0, 140,   0, 105, 105,
-	190, 190, 250,   0, 250,   0,  16,  16,
-	 16,   7,  45,   8,  18,  90, 120, 250,
-	  0,  80, 180,   8,  18,   7,  15,  17,
-	 19,  21,  75,  35,   0,  85,  11,  10,
-	 67,  86,  95,  30,  25,  18,
-};
-assert_compile(lengthof(_housetype_population) == HOUSE_MAX);
-
-static const byte _housetype_mailamount[] = {
-	70, 55, 20,  2, 85, 85, 12, 22,
-	22,  0,  0,  0,  0, 65, 48, 48,
-	48, 50, 10, 55,  5,  5,  5,  5,
-	 6,  7,  8, 35, 50, 40, 64, 23,
-	 5,  5,  5,  5, 65,  6,  6, 23,
-	 5,  5,  5,  5, 20, 20,  6,  6,
-	 6,  6, 60, 60, 70, 70, 80, 80,
-	 5,  5, 20, 20,  2,  2,  7,  7,
-	45, 45, 25, 25, 25, 25, 50, 50,
-	75, 75, 60, 60, 60, 60,  6,  6,
-	 5,  4, 15,  3,  7, 24, 25, 80,
-	80, 23, 90,  3,  5,  3,  6,  6,
-	 6,  6, 20,  9,  0, 18,  3,  3,
-	22, 23, 28, 10,  8,  7,
-};
-assert_compile(lengthof(_housetype_mailamount) == HOUSE_MAX);
-
-static const byte _housetype_remove_cost[] = {
-	 150, 140, 100,  90, 160, 160,  80, 180,
-	 180,  65,  65,  60,  60, 130, 110, 105,
-	 107, 200, 145, 155, 250, 250, 250, 250,
-	  70,  75,  71, 135, 145, 132, 155, 220,
-	 250, 250, 250, 250, 170,  70,  70, 210,
-	 250, 250, 250, 250, 100, 100,  70,  70,
-	  80,  80, 150, 150, 170, 170, 200, 200,
-	  60,  60, 100, 100,  85,  85,  80,  80,
-	 140, 140, 160, 160, 160, 160, 130, 130,
-	 190, 190, 140, 140, 140, 140,  80,  80,
-	  80,  30, 130,  90,  80, 110, 120, 190,
-	 190, 110, 180,  90,  90,  70,  80,  80,
-	  80,  80, 160,  90,  90, 150,  60,  60,
-	 140, 145, 165,  90,  75,  85,
-};
-assert_compile(lengthof(_housetype_remove_cost) == HOUSE_MAX);
+/* 4 variants * 4 build stages */
+assert_compile(lengthof(_town_draw_tile_data) == (NEW_HOUSE_OFFSET) * 4 * 4);
 
-static const uint16 _housetype_remove_ratingmod[] = {
-	 140, 130,  90, 230, 160, 160,  80, 150,
-	 150,  40,  40,  75,  75, 110, 100, 100,
-	 100, 150, 110, 110, 300, 300, 300, 300,
-	  75,  75,  75, 100, 170, 135, 180, 230,
-	 300, 300, 300, 300, 250,  75,  75, 230,
-	 300, 300, 300, 300,  90,  90,  70,  70,
-	  70,  70, 120, 120, 130, 130, 140, 140,
-	  60,  60,  80,  80, 230, 230,  80,  80,
-	 110, 110, 160, 160, 160, 160, 105, 105,
-	 135, 135, 200, 200, 200, 200,  80,  80,
-	  80,  30,  95, 200,  80,  95,  95, 140,
-	 140,  95, 150, 200,  90,  50,  75,  75,
-	  75,  75, 130,  80,  80, 130,  45,  45,
-	 130, 130, 130,  70,  65,  95,
-};
-assert_compile(lengthof(_housetype_remove_ratingmod) == HOUSE_MAX);
-
-
-struct HousetypeYear {
-	Year min, max;
+/** Describes the data that defines each house in the game
+ * @param mnd introduction year of the house
+ * @param mxd last year it can be built
+ * @param p   population
+ * @param rc  cost multiplier for removing it
+ * @param bn  building name
+ * @param rr  rating decrease if removed
+ * @param mg  mail generation multiplier
+ * @param pa  passenger acceptance
+ * @param ma  mail acceptance
+ * @param ga  goods acceptance
+ * @param fa  food acceptance
+ * @param bf  building flags (size, stadium etc...)
+ * @param ba  building availability (zone, climate...)
+ * @see HouseSpec
+ */
+#define M(mnd, mxd, p, rc, bn, rr, mg, pa, ma, ga, fa, bf, ba) \
+	{mnd, mxd, p, rc, bn, rr, mg, pa, ma, ga, fa, bf, ba, true, \
+	 0, NULL, 0, 0, {0, 0, 0, 0}, 16, NO_EXTRA_FLAG, HOUSE_NO_CLASS, 0, 2, 0, 0, NULL}
+static const HouseSpec _original_house_specs[] = {
+	/**
+	 *                                                              remove_rating_decrease
+	 *                                                               |    mail_generation
+	 *     min_date                                                  |    |    passenger_acceptance
+	 *     |         max_date                                        |    |    |    mail_acceptance
+	 *     |         |    population                                 |    |    |    |    goods_acceptance
+	 *     |         |    |    removal_cost                          |    |    |    |    |    food_acceptance
+	 *     |         |    |    |    building_name                    |    |    |    |    |    |
+	 *     |         |    |    |    |                                |    |    |    |    |    |
+	 *     |         |    |    |    |                                |    |    |    |    |    |
+	 * +-building_flags   |    |    |                                |    |    |    |    |    |
+	 * +-building_availability |    |                                |    |    |    |    |    |
+	 * |   |         |    |    |    |                                |    |    |    |    |    |*/
+	M( 1963, MAX_YEAR, 187, 150, STR_200F_TALL_OFFICE_BLOCK,      140,  70,   8,   3,   4,   0,
+	   TILE_SIZE_1x1,
+	   HZ_TEMP | HZ_ZON5),
+	M( 1957, MAX_YEAR,  85, 140, STR_2010_OFFICE_BLOCK,           130,  55,   8,   3,   4,   0,
+	   TILE_SIZE_1x1,
+	   HZ_TEMP | HZ_ZON5 | HZ_ZON4),
+	M( 1968, MAX_YEAR,  40, 100, STR_2011_SMALL_BLOCK_OF_FLATS,    90,  20,   8,   3,   1,   0,
+	   TILE_SIZE_1x1,
+	   HZ_TEMP | HZ_ZON4 | HZ_ZON3 | HZ_ZON2),
+	M(    0, MAX_YEAR,   5,  90, STR_2012_CHURCH,                 230,   2,   2,   0,   0,   0,
+	   BUILDING_IS_CHURCH | TILE_SIZE_1x1,
+	   HZ_TEMP | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1),
+	M( 1975, MAX_YEAR, 220, 160, STR_2013_LARGE_OFFICE_BLOCK,     160,  85,  10,   4,   6,   0,
+	   BUILDING_IS_ANIMATED | TILE_SIZE_1x1,
+	   HZ_TEMP | HZ_SUBARTC_BELOW | HZ_SUBTROPIC | HZ_ZON5),
+	M( 1975, MAX_YEAR, 220, 160, STR_2013_LARGE_OFFICE_BLOCK,     160,  85,  10,   4,   6,   0,
+	   BUILDING_IS_ANIMATED | TILE_SIZE_1x1,
+	   HZ_SUBARTC_ABOVE  | HZ_ZON5),
+	M(    0, MAX_YEAR,  30,  80, STR_2014_TOWN_HOUSES,             80,  12,   4,   1,   0,   0,
+	   TILE_SIZE_1x1,
+	   HZ_TEMP | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1),
+	M( 1959, MAX_YEAR, 140, 180, STR_2015_HOTEL,                  150,  22,   6,   1,   2,   0,
+	   TILE_SIZE_1x2,
+	   HZ_TEMP | HZ_ZON5 | HZ_ZON3),
+	M( 1959, MAX_YEAR,   0, 180, STR_2015_HOTEL,                  150,  22,   6,   1,   2,   0,
+	   TILE_NO_FLAG,
+	   HZ_NOZNS),
+	M( 1945, MAX_YEAR,   0,  65, STR_2016_STATUE,                  40,   0,   2,   0,   0,   0,
+	   TILE_SIZE_1x1,
+	   HZ_TEMP | HZ_SUBARTC_BELOW | HZ_SUBTROPIC | HZ_ZON5 | HZ_ZON4),
+	M( 1945, MAX_YEAR,   0,  65, STR_2017_FOUNTAIN,                40,   0,   2,   0,   0,   0,
+	   TILE_SIZE_1x1,
+	   HZ_TEMP | HZ_SUBARTC_BELOW | HZ_SUBTROPIC | HZ_ZON5),
+	M(    0, MAX_YEAR,   0,  60, STR_2018_PARK,                    75,   0,   2,   0,   0,   0,
+	   TILE_SIZE_1x1,
+	   HZ_TEMP | HZ_ZON3),
+	M( 1935, MAX_YEAR,   0,  60, STR_2018_PARK,                    75,   0,   2,   0,   0,   0,
+	   TILE_SIZE_1x1,
+	   HZ_TEMP | HZ_ZON4),
+	M( 1951, MAX_YEAR, 150, 130, STR_2019_OFFICE_BLOCK,           110,  65,   8,   2,   4,   0,
+	   TILE_SIZE_1x1,
+	   HZ_TEMP | HZ_ZON5 | HZ_ZON4),
+	M( 1930, 1960,      95, 110, STR_201A_SHOPS_AND_OFFICES,      100,  48,   6,   2,   3,   0,
+	   TILE_SIZE_1x1,
+	   HZ_TEMP | HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
+	M( 1930, 1960,      95, 105, STR_201A_SHOPS_AND_OFFICES,      100,  48,   6,   2,   3,   0,
+	   TILE_SIZE_1x1,
+	   HZ_TEMP | HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
+	M( 1930, 1960,      95, 107, STR_201A_SHOPS_AND_OFFICES,      100,  48,   6,   2,   3,   0,
+	   TILE_SIZE_1x1,
+	   HZ_TEMP | HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
+	M( 1977, MAX_YEAR, 130, 200, STR_201B_MODERN_OFFICE_BUILDING, 150,  50,  10,   3,   6,   0,
+	   TILE_SIZE_1x1,
+	   HZ_TEMP | HZ_SUBARTC_BELOW | HZ_SUBTROPIC | HZ_ZON5),
+	M( 1983, MAX_YEAR,   6, 145, STR_201C_WAREHOUSE,              110,  10,   6,   3,   8,   0,
+	   TILE_SIZE_1x1,
+	   HZ_TEMP | HZ_ZON5),
+	M( 1985, MAX_YEAR, 110, 155, STR_201D_OFFICE_BLOCK,           110,  55,   6,   2,   6,   0,
+	   TILE_SIZE_1x1,
+	   HZ_TEMP | HZ_ZON5),
+	M(    0, MAX_YEAR,  65, 250, STR_201E_STADIUM,                300,   5,   4,   0,   0,   0,
+	   BUILDING_IS_STADIUM | TILE_SIZE_2x2,
+	   HZ_TEMP | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1),
+	M(    0, MAX_YEAR,   0, 250, STR_201E_STADIUM,                300,   5,   4,   0,   0,   0,
+	   TILE_NO_FLAG,
+	   HZ_NOZNS),
+	M(    0, MAX_YEAR,   0, 250, STR_201E_STADIUM,                300,   5,   4,   0,   0,   0,
+	   TILE_NO_FLAG,
+	   HZ_NOZNS),
+	M(    0, MAX_YEAR,   0, 250, STR_201E_STADIUM,                300,   5,   4,   0,   0,   0,
+	   TILE_NO_FLAG,
+	   HZ_NOZNS),
+	M(    0, 1951,      15,  70, STR_201F_OLD_HOUSES,              75,   6,   3,   1,   0,   0,
+	   TILE_SIZE_1x1,
+	   HZ_TEMP | HZ_ZON2 | HZ_ZON1),
+	M(    0, 1952,      12,  75, STR_2036_COTTAGES,                75,   7,   3,   1,   0,   0,
+	   TILE_SIZE_1x1,
+	   HZ_TEMP | HZ_ZON1),
+	M( 1931, MAX_YEAR,  13,  71, STR_2037_HOUSES,                  75,   8,   3,   1,   0,   0,
+	   TILE_SIZE_1x1,
+	   HZ_TEMP | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1),
+	M( 1935, MAX_YEAR, 100, 135, STR_2038_FLATS,                  100,  35,   7,   2,   2,   0,
+	   TILE_SIZE_1x1,
+	   HZ_TEMP | HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
+	M( 1963, MAX_YEAR, 170, 145, STR_2039_TALL_OFFICE_BLOCK,      170,  50,   8,   3,   3,   0,
+	   TILE_SIZE_1x1,
+	   HZ_TEMP | HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
+	M(    0, 1955,     100, 132, STR_203A_SHOPS_AND_OFFICES,      135,  40,   6,   2,   3,   0,
+	   TILE_SIZE_1x1,
+	   HZ_TEMP | HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
+	M( 1973, MAX_YEAR, 180, 155, STR_203B_SHOPS_AND_OFFICES,      180,  64,   8,   3,   3,   0,
+	   TILE_SIZE_1x1,
+	   HZ_TEMP | HZ_SUBTROPIC | HZ_ZON5 | HZ_ZON3),
+	M(    0, MAX_YEAR,  35, 220, STR_203C_THEATER,                230,  23,   8,   2,   2,   0,
+	   TILE_SIZE_1x1,
+	   HZ_TEMP | HZ_ZON5 | HZ_ZON4),
+	M( 1958, MAX_YEAR,  65, 250, STR_203D_STADIUM,                300,   5,   4,   0,   0,   0,
+	   BUILDING_IS_STADIUM | TILE_SIZE_2x2,
+	   HZ_TEMP | HZ_SUBARTC_BELOW | HZ_SUBTROPIC | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1),
+	M( 1958, MAX_YEAR,   0, 250, STR_203D_STADIUM,                300,   5,   4,   0,   0,   0,
+	   TILE_NO_FLAG,
+	   HZ_NOZNS),
+	M( 1958, MAX_YEAR,   0, 250, STR_203D_STADIUM,                300,   5,   4,   0,   0,   0,
+	   TILE_NO_FLAG,
+	   HZ_NOZNS),
+	M( 1958, MAX_YEAR,   0, 250, STR_203D_STADIUM,                300,   5,   4,   0,   0,   0,
+	   TILE_NO_FLAG,
+	   HZ_NOZNS),
+	M( 2000, MAX_YEAR, 140, 170, STR_203E_OFFICES,                250,  65,   8,   3,   2,   0,
+	   TILE_SIZE_1x1,
+	   HZ_TEMP | HZ_SUBARTC_BELOW | HZ_SUBTROPIC | HZ_ZON5 | HZ_ZON4),
+	M(    0, 1960,      15,  70, STR_203F_HOUSES,                  75,   6,   3,   1,   0,   1,
+	   TILE_SIZE_1x1,
+	   HZ_SUBARTC_BELOW | HZ_ZON2 | HZ_ZON1),
+	M(    0, 1960,      15,  70, STR_203F_HOUSES,                  75,   6,   3,   1,   0,   1,
+	   TILE_SIZE_1x1,
+	   HZ_SUBARTC_ABOVE | HZ_ZON2 | HZ_ZON1),
+	M( 1945, MAX_YEAR,  35, 210, STR_2040_CINEMA,                 230,  23,   8,   2,   2,   0,
+	   TILE_SIZE_1x1,
+	   HZ_TEMP | HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
+	M( 1983, MAX_YEAR, 180, 250, STR_2041_SHOPPING_MALL,          300,   5,   8,   2,   3,   0,
+	   TILE_SIZE_2x2,
+	   HZ_TEMP | HZ_ZON5 | HZ_ZON4 | HZ_ZON3 |HZ_ZON2),
+	M( 1983, MAX_YEAR,   0, 250, STR_2041_SHOPPING_MALL,          300,   5,   8,   2,   3,   0,
+	   TILE_NO_FLAG,
+	   HZ_NOZNS),
+	M( 1983, MAX_YEAR,   0, 250, STR_2041_SHOPPING_MALL,          300,   5,   8,   2,   3,   0,
+	   TILE_NO_FLAG,
+	   HZ_NOZNS),
+	M( 1983, MAX_YEAR,   0, 250, STR_2041_SHOPPING_MALL,          300,   5,   8,   2,   3,   0,
+	   TILE_NO_FLAG,
+	   HZ_NOZNS),
+	M(    0, MAX_YEAR,  80, 100, STR_2038_FLATS,                   90,  20,   5,   2,   0,   2,
+	   TILE_SIZE_1x1,
+	   HZ_SUBARTC_BELOW | HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
+	M(    0, MAX_YEAR,  80, 100, STR_2038_FLATS,                   90,  20,   5,   2,   0,   2,
+	   TILE_SIZE_1x1,
+	   HZ_SUBARTC_ABOVE  | HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
+	M(    0, MAX_YEAR,  16,  70, STR_203F_HOUSES,                  70,   6,   3,   1,   0,   2,
+	   TILE_SIZE_1x1,
+	   HZ_SUBARTC_BELOW | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1),
+	M(    0, MAX_YEAR,  16,  70, STR_203F_HOUSES,                  70,   6,   3,   1,   0,   2,
+	   TILE_SIZE_1x1,
+	   HZ_SUBARTC_ABOVE | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1),
+	M(    0, 1963,      14,  80, STR_203F_HOUSES,                  70,   6,   3,   1,   0,   2,
+	   TILE_SIZE_1x1,
+	   HZ_SUBARTC_BELOW | HZ_ZON3 | HZ_ZON2 | HZ_ZON1),
+	M(    0, 1963,      14,  80, STR_203F_HOUSES,                  70,   6,   3,   1,   0,   2,
+	   TILE_SIZE_1x1,
+	   HZ_SUBARTC_ABOVE | HZ_ZON3 | HZ_ZON2 | HZ_ZON1),
+	M( 1966, MAX_YEAR, 135, 150, STR_200F_TALL_OFFICE_BLOCK,      120,  60,   8,   3,   4,   0,
+	   TILE_SIZE_1x1,
+	   HZ_SUBARTC_BELOW | HZ_SUBTROPIC | HZ_ZON5 | HZ_ZON4),
+	M( 1966, MAX_YEAR, 135, 150, STR_200F_TALL_OFFICE_BLOCK,      120,  60,   8,   3,   4,   0,
+	   TILE_SIZE_1x1,
+	   HZ_SUBARTC_ABOVE | HZ_ZON5 | HZ_ZON4),
+	M( 1970, MAX_YEAR, 170, 170, STR_200F_TALL_OFFICE_BLOCK,      130,  70,   9,   3,   4,   0,
+	   TILE_SIZE_1x1,
+	   HZ_SUBARTC_BELOW | HZ_ZON5 | HZ_ZON4),
+	M( 1970, MAX_YEAR, 170, 170, STR_200F_TALL_OFFICE_BLOCK,      130,  70,   9,   3,   4,   0,
+	   TILE_SIZE_1x1,
+	   HZ_SUBARTC_ABOVE | HZ_ZON5 | HZ_ZON4),
+	M( 1974, MAX_YEAR, 210, 200, STR_200F_TALL_OFFICE_BLOCK,      140,  80,  10,   3,   5,   0,
+	   TILE_SIZE_1x1,
+	   HZ_SUBARTC_BELOW | HZ_SUBTROPIC | HZ_ZON5 | HZ_ZON4),
+	M( 1974, MAX_YEAR, 210, 200, STR_200F_TALL_OFFICE_BLOCK,      140,  80,  10,   3,   5,   0,
+	   TILE_SIZE_1x1,
+	   HZ_SUBARTC_ABOVE | HZ_ZON5 | HZ_ZON4),
+	M(    0, MAX_YEAR,  10,  60, STR_203F_HOUSES,                  60,   5,   2,   1,   0,   1,
+	   TILE_SIZE_1x1,
+	   HZ_SUBARTC_BELOW | HZ_ZON1),
+	M(    0, MAX_YEAR,  10,  60, STR_203F_HOUSES,                  60,   5,   2,   1,   0,   1,
+	   TILE_SIZE_1x1,
+	   HZ_SUBARTC_ABOVE | HZ_ZON1),
+	M(    0, MAX_YEAR,  25, 100, STR_201A_SHOPS_AND_OFFICES,       80,  20,   3,   1,   0,   1,
+	   TILE_SIZE_1x1,
+	   HZ_SUBARTC_BELOW | HZ_ZON5 | HZ_ZON4 | HZ_ZON3 | HZ_ZON2),
+	M(    0, MAX_YEAR,  25, 100, STR_201A_SHOPS_AND_OFFICES,       80,  20,   3,   1,   0,   1,
+	   TILE_SIZE_1x1,
+	   HZ_SUBARTC_ABOVE | HZ_ZON5 | HZ_ZON4 | HZ_ZON3 | HZ_ZON2),
+	M(    0, MAX_YEAR,   6,  85, STR_2012_CHURCH,                 230,   2,   2,   0,   0,   0,
+	   BUILDING_IS_CHURCH | TILE_SIZE_1x1,
+	   HZ_SUBARTC_BELOW | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1),
+	M(    0, MAX_YEAR,   6,  85, STR_2012_CHURCH,                 230,   2,   2,   0,   0,   0,
+	   BUILDING_IS_CHURCH | TILE_SIZE_1x1,
+	   HZ_SUBARTC_ABOVE | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1),
+	M(    0, MAX_YEAR,  17,  80, STR_203F_HOUSES,                  80,   7,   3,   1,   0,   1,
+	   TILE_SIZE_1x1,
+	   HZ_SUBARTC_BELOW | HZ_ZON3 | HZ_ZON2 | HZ_ZON1),
+	M(    0, MAX_YEAR,  17,  80, STR_203F_HOUSES,                  80,   7,   3,   1,   0,   1,
+	   TILE_SIZE_1x1,
+	   HZ_SUBARTC_ABOVE | HZ_ZON3 | HZ_ZON2 | HZ_ZON1),
+	M(    0, 1960,      90, 140, STR_201A_SHOPS_AND_OFFICES,      110,  45,   6,   2,   3,   0,
+	   TILE_SIZE_1x1,
+	   HZ_SUBARTC_BELOW| HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
+	M(    0, 1960,      90, 140, STR_201A_SHOPS_AND_OFFICES,      110,  45,   6,   2,   3,   0,
+	   TILE_SIZE_1x1,
+	   HZ_SUBARTC_ABOVE| HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
+	M( 1972, MAX_YEAR, 140, 160, STR_2015_HOTEL,                  160,  25,   6,   1,   0,   3,
+	   TILE_SIZE_1x2,
+	   HZ_SUBARTC_BELOW| HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
+	M( 1972, MAX_YEAR,   0, 160, STR_2015_HOTEL,                  160,  25,   6,   1,   2,   0,
+	   TILE_NO_FLAG,
+	   HZ_NOZNS),
+	M( 1972, MAX_YEAR, 140, 160, STR_2015_HOTEL,                  160,  25,   6,   1,   0,   3,
+	   TILE_SIZE_1x2,
+	   HZ_SUBARTC_ABOVE| HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
+	M( 1972, MAX_YEAR,   0, 160, STR_2015_HOTEL,                  160,  25,   6,   1,   2,   0,
+	   TILE_NO_FLAG,
+	   HZ_NOZNS),
+	M( 1963, MAX_YEAR, 105, 130, STR_201A_SHOPS_AND_OFFICES,      105,  50,   7,   2,   3,   0,
+	   TILE_SIZE_1x1,
+	   HZ_SUBARTC_BELOW | HZ_SUBTROPIC | HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
+	M( 1963, MAX_YEAR, 105, 130, STR_201A_SHOPS_AND_OFFICES,      105,  50,   7,   2,   3,   0,
+	   TILE_SIZE_1x1,
+	   HZ_SUBARTC_ABOVE| HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
+	M( 1978, MAX_YEAR, 190, 190, STR_200F_TALL_OFFICE_BLOCK,      135,  75,   9,   3,   4,   0,
+	   TILE_SIZE_1x1,
+	   HZ_SUBARTC_BELOW | HZ_ZON5 | HZ_ZON4),
+	M( 1978, MAX_YEAR, 190, 190, STR_200F_TALL_OFFICE_BLOCK,      135,  75,   9,   3,   4,   0,
+	   TILE_SIZE_1x1,
+	   HZ_SUBARTC_ABOVE | HZ_ZON5 | HZ_ZON4),
+	M( 1967, MAX_YEAR, 250, 140, STR_200F_TALL_OFFICE_BLOCK,      200,  60,   7,   2,   2,   0,
+	   TILE_SIZE_2x1,
+	   HZ_SUBARTC_BELOW| HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
+	M( 1967, MAX_YEAR,   0, 140, STR_200F_TALL_OFFICE_BLOCK,      200,  60,   7,   2,   2,   0,
+	   TILE_NO_FLAG,
+	   HZ_NOZNS),
+	M( 1967, MAX_YEAR, 250, 140, STR_200F_TALL_OFFICE_BLOCK,      200,  60,   7,   2,   2,   0,
+	   TILE_SIZE_2x1,
+	   HZ_SUBARTC_ABOVE | HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
+	M( 1967, MAX_YEAR,   0, 140, STR_200F_TALL_OFFICE_BLOCK,      200,  60,   7,   2,   2,   0,
+	   TILE_NO_FLAG,
+	   HZ_NOZNS),
+	M(    0, MAX_YEAR,  16,  80, STR_203F_HOUSES,                  80,   6,   3,   1,   0,   2,
+	   TILE_SIZE_1x1,
+	   HZ_SUBTROPIC | HZ_ZON5 | HZ_ZON4 | HZ_ZON3 | HZ_ZON2),
+	M(    0, MAX_YEAR,  16,  80, STR_203F_HOUSES,                  80,   6,   3,   1,   0,   2,
+	   TILE_SIZE_1x1,
+	   HZ_SUBTROPIC | HZ_ZON5 | HZ_ZON4 | HZ_ZON3 | HZ_ZON2),
+	M(    0, MAX_YEAR,  16,  80, STR_203F_HOUSES,                  80,   5,   3,   1,   0,   2,
+	   TILE_SIZE_1x1,
+	   HZ_SUBTROPIC | HZ_ZON5 | HZ_ZON4 | HZ_ZON3 | HZ_ZON2),
+	M(    0, MAX_YEAR,   7,  30, STR_203F_HOUSES,                  30,   4,   3,   1,   0,   1,
+	   TILE_SIZE_1x1,
+	   HZ_SUBTROPIC | HZ_ZON1),
+	M(    0, MAX_YEAR,  45, 130, STR_2038_FLATS,                   95,  15,   6,   2,   1,   0,
+	   TILE_SIZE_1x1,
+	   HZ_SUBTROPIC | HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
+	M(    0, MAX_YEAR,   8,  90, STR_2012_CHURCH,                 200,   3,   2,   0,   0,   0,
+	   BUILDING_IS_CHURCH | TILE_SIZE_1x1,
+	   HZ_SUBTROPIC | HZ_ZON4 | HZ_ZON3 | HZ_ZON2),
+	M(    0, MAX_YEAR,  18,  80, STR_203F_HOUSES,                  80,   7,   3,   1,   0,   2,
+	   TILE_SIZE_1x1,
+	   HZ_SUBTROPIC | HZ_ZON5 | HZ_ZON4 | HZ_ZON3 | HZ_ZON2),
+	M( 1973, MAX_YEAR,  90, 110, STR_2038_FLATS,                   95,  24,   6,   2,   1,   0,
+	   TILE_SIZE_1x1,
+	   HZ_SUBTROPIC | HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
+	M( 1962, MAX_YEAR, 120, 120, STR_2038_FLATS,                   95,  25,   6,   2,   1,   0,
+	   TILE_SIZE_1x1,
+	   HZ_SUBTROPIC | HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
+	M( 1984, MAX_YEAR, 250, 190, STR_200F_TALL_OFFICE_BLOCK,      140,  80,   8,   3,   4,   0,
+	   TILE_SIZE_2x1,
+	   HZ_SUBTROPIC | HZ_ZON5 | HZ_ZON4),
+	M( 1984, MAX_YEAR,   0, 190, STR_200F_TALL_OFFICE_BLOCK,      140,  80,   8,   3,   4,   0,
+	   TILE_NO_FLAG,
+	   HZ_SUBTROPIC),
+	M(    0, MAX_YEAR,  80, 110, STR_2038_FLATS,                   95,  23,   6,   2,   1,   0,
+	   TILE_SIZE_1x1,
+	   HZ_SUBTROPIC | HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
+	M( 1993, MAX_YEAR, 180, 180, STR_200F_TALL_OFFICE_BLOCK,      150,  90,   8,   3,   4,   0,
+	   TILE_SIZE_1x1,
+	   HZ_SUBTROPIC | HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
+	M(    0, MAX_YEAR,   8,  90, STR_2012_CHURCH,                 200,   3,   2,   0,   0,   0,
+	   BUILDING_IS_CHURCH | TILE_SIZE_1x1,
+	   HZ_TOYLND | HZ_ZON5 | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1),
+	M(    0, MAX_YEAR,  18,  90, STR_203F_HOUSES,                  90,   5,   6,   2,   2,   0,
+	   TILE_SIZE_1x1,
+	   HZ_TOYLND | HZ_ZON5 | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1),
+	M(    0, MAX_YEAR,   7,  70, STR_203F_HOUSES,                  50,   3,   3,   1,   1,   0,
+	   TILE_SIZE_1x1,
+	   HZ_TOYLND | HZ_ZON2 | HZ_ZON1),
+	M(    0, MAX_YEAR,  15,  80, STR_203F_HOUSES,                  75,   6,   3,   1,   2,   0,
+	   TILE_SIZE_1x1,
+	   HZ_TOYLND | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1),
+	M(    0, MAX_YEAR,  17,  80, STR_203F_HOUSES,                  75,   6,   3,   1,   2,   0,
+	   TILE_SIZE_1x1,
+	   HZ_TOYLND | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1),
+	M(    0, MAX_YEAR,  19,  80, STR_203F_HOUSES,                  75,   6,   3,   1,   2,   0,
+	   TILE_SIZE_1x1,
+	   HZ_TOYLND | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1),
+	M(    0, MAX_YEAR,  21,  80, STR_203F_HOUSES,                  75,   6,   3,   1,   2,   0,
+	   TILE_SIZE_1x1,
+	   HZ_TOYLND | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1),
+	M(    0, MAX_YEAR,  75, 160, STR_200F_TALL_OFFICE_BLOCK,      130,  20,   8,   4,   2,   0,
+	   TILE_SIZE_1x1,
+	   HZ_TOYLND | HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
+	M(    0, MAX_YEAR,  35,  90, STR_203F_HOUSES,                  80,   9,   4,   1,   2,   0,
+	   TILE_SIZE_1x2,
+	   HZ_TOYLND | HZ_ZON5 | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1),
+	M(    0, MAX_YEAR,   0,  90, STR_203F_HOUSES,                  80,   0,   4,   1,   2,   0,
+	   TILE_NO_FLAG,
+	   HZ_NOZNS),
+	M(    0, MAX_YEAR,  85, 150, STR_200F_TALL_OFFICE_BLOCK,      130,  18,   8,   4,   2,   0,
+	   TILE_SIZE_1x1,
+	   HZ_TOYLND | HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
+	M(    0, MAX_YEAR,  11,  60, STR_2059_IGLOO,                   45,   3,   3,   1,   1,   0,
+	   TILE_SIZE_1x1,
+	   HZ_TOYLND | HZ_ZON1),
+	M(    0, MAX_YEAR,  10,  60, STR_205A_TEPEES,                  45,   3,   3,   1,   1,   0,
+	   TILE_SIZE_1x1,
+	   HZ_TOYLND | HZ_ZON1),
+	M(    0, MAX_YEAR,  67, 140, STR_201A_SHOPS_AND_OFFICES,      130,  22,   8,   4,   0,   4,
+	   TILE_SIZE_1x1,
+	   HZ_TOYLND | HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
+	M(    0, MAX_YEAR,  86, 145, STR_201A_SHOPS_AND_OFFICES,      130,  23,   8,   4,   0,   4,
+	   TILE_SIZE_1x1,
+	   HZ_TOYLND | HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
+	M(    0, MAX_YEAR,  95, 165, STR_200F_TALL_OFFICE_BLOCK,      130,  28,   8,   4,   2,   0,
+	   TILE_SIZE_1x1,
+	   HZ_TOYLND | HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
+	M(    0, MAX_YEAR,  30,  90, STR_2016_STATUE,                  70,  10,   4,   1,   2,   0,
+	   TILE_SIZE_1x1,
+	   HZ_TOYLND | HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
+	M(    0, MAX_YEAR,  25,  75, STR_205B_TEAPOT_HOUSE,            65,   8,   3,   1,   2,   0,
+	   TILE_SIZE_1x1,
+	   HZ_TOYLND | HZ_ZON5 | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1),
+	M(    0, MAX_YEAR,  18,  85, STR_205C_PIGGY_BANK,              95,   7,   3,   2,   0,   4,
+	   TILE_SIZE_1x1,
+	   HZ_TOYLND | HZ_ZON5 | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1),
 };
-
-static const HousetypeYear _housetype_years[] = {
-	{ 1963, MAX_YEAR },
-	{ 1957, MAX_YEAR },
-	{ 1968, MAX_YEAR },
-	{    0, MAX_YEAR },
-	{ 1975, MAX_YEAR },
-	{ 1975, MAX_YEAR },
-	{    0, MAX_YEAR },
-	{ 1959, MAX_YEAR },
-	{ 1959, MAX_YEAR },
-	{ 1945, MAX_YEAR },
-	{ 1945, MAX_YEAR },
-	{    0, MAX_YEAR },
-	{ 1935, MAX_YEAR },
-	{ 1951, MAX_YEAR },
-	{ 1930,     1960 },
-	{ 1930,     1960 },
-	{ 1930,     1960 },
-	{ 1977, MAX_YEAR },
-	{ 1983, MAX_YEAR },
-	{ 1985, MAX_YEAR },
-	{    0, MAX_YEAR },
-	{    0, MAX_YEAR },
-	{    0, MAX_YEAR },
-	{    0, MAX_YEAR },
-	{    0,     1951 },
-	{    0,     1952 },
-	{ 1931, MAX_YEAR },
-	{ 1935, MAX_YEAR },
-	{ 1963, MAX_YEAR },
-	{    0,     1955 },
-	{ 1973, MAX_YEAR },
-	{    0, MAX_YEAR },
-	{ 1958, MAX_YEAR },
-	{ 1958, MAX_YEAR },
-	{ 1958, MAX_YEAR },
-	{ 1958, MAX_YEAR },
-	{ 2000, MAX_YEAR },
-	{    0,     1960 },
-	{    0,     1960 },
-	{ 1945, MAX_YEAR },
-	{ 1983, MAX_YEAR },
-	{ 1983, MAX_YEAR },
-	{ 1983, MAX_YEAR },
-	{ 1983, MAX_YEAR },
-	{    0, MAX_YEAR },
-	{    0, MAX_YEAR },
-	{    0, MAX_YEAR },
-	{    0, MAX_YEAR },
-	{    0,     1963 },
-	{    0,     1963 },
-	{ 1966, MAX_YEAR },
-	{ 1966, MAX_YEAR },
-	{ 1970, MAX_YEAR },
-	{ 1970, MAX_YEAR },
-	{ 1974, MAX_YEAR },
-	{ 1974, MAX_YEAR },
-	{    0, MAX_YEAR },
-	{    0, MAX_YEAR },
-	{    0, MAX_YEAR },
-	{    0, MAX_YEAR },
-	{    0, MAX_YEAR },
-	{    0, MAX_YEAR },
-	{    0, MAX_YEAR },
-	{    0, MAX_YEAR },
-	{    0,     1960 },
-	{    0,     1960 },
-	{ 1972, MAX_YEAR },
-	{ 1972, MAX_YEAR },
-	{ 1972, MAX_YEAR },
-	{ 1972, MAX_YEAR },
-	{ 1963, MAX_YEAR },
-	{ 1963, MAX_YEAR },
-	{ 1978, MAX_YEAR },
-	{ 1978, MAX_YEAR },
-	{ 1967, MAX_YEAR },
-	{ 1967, MAX_YEAR },
-	{ 1967, MAX_YEAR },
-	{ 1967, MAX_YEAR },
-	{    0, MAX_YEAR },
-	{    0, MAX_YEAR },
-	{    0, MAX_YEAR },
-	{    0, MAX_YEAR },
-	{    0, MAX_YEAR },
-	{    0, MAX_YEAR },
-	{    0, MAX_YEAR },
-	{ 1973, MAX_YEAR },
-	{ 1962, MAX_YEAR },
-	{ 1984, MAX_YEAR },
-	{ 1984, MAX_YEAR },
-	{    0, MAX_YEAR },
-	{ 1993, MAX_YEAR },
-	{    0, MAX_YEAR },
-	{    0, MAX_YEAR },
-	{    0, MAX_YEAR },
-	{    0, MAX_YEAR },
-	{    0, MAX_YEAR },
-	{    0, MAX_YEAR },
-	{    0, MAX_YEAR },
-	{    0, MAX_YEAR },
-	{    0, MAX_YEAR },
-	{    0, MAX_YEAR },
-	{    0, MAX_YEAR },
-	{    0, MAX_YEAR },
-	{    0, MAX_YEAR },
-	{    0, MAX_YEAR },
-	{    0, MAX_YEAR },
-	{    0, MAX_YEAR },
-	{    0, MAX_YEAR },
-	{    0, MAX_YEAR },
-	{    0, MAX_YEAR },
-};
-assert_compile(lengthof(_housetype_years) == HOUSE_MAX);
-
-static const byte _housetype_cargo_passengers[] = {
-	8,  8,  8,  2, 10, 10,  4,  6,
-	6,  2,  2,  2,  2,  8,  6,  6,
-	6, 10,  6,  6,  4,  4,  4,  4,
-	3,  3,  3,  7,  8,  6,  8,  8,
-	4,  4,  4,  4,  8,  3,  3,  8,
-	8,  8,  8,  8,  5,  5,  3,  3,
-	3,  3,  8,  8,  9,  9, 10, 10,
-	2,  2,  3,  3,  2,  2,  3,  3,
-	6,  6,  6,  6,  6,  6,  7,  7,
-	9,  9,  7,  7,  7,  7,  3,  3,
-	3,  3,  6,  2,  3,  6,  6,  8,
-	8,  6,  8,  2,  6,  3,  3,  3,
-	3,  3,  8,  4,  4,  8,  3,  3,
-	8,  8,  8,  4,  3,  3,
-};
-assert_compile(lengthof(_housetype_cargo_passengers) == HOUSE_MAX);
-
-static const byte _housetype_cargo_mail[] = {
-	 3, 3, 3, 0, 4, 4, 1, 1,
-	 1, 0, 0, 0, 0, 2, 2, 2,
-	 2, 3, 3, 2, 0, 0, 0, 0,
-	 1, 1, 1, 2, 3, 2, 3, 2,
-	 0, 0, 0, 0, 3, 1, 1, 2,
-	 2, 2, 2, 2, 2, 2, 1, 1,
-	 1, 1, 3, 3, 3, 3, 3, 3,
-	 1, 1, 1, 1, 0, 0, 1, 1,
-	 2, 2, 1, 1, 1, 1, 2, 2,
-	 3, 3, 2, 2, 2, 2, 1, 1,
-	 1, 1, 2, 0, 1, 2, 2, 3,
-	 3, 2, 3, 0, 2, 1, 1, 1,
-	 1, 1, 4, 1, 1, 4, 1, 1,
-	 4, 4, 4, 1, 1, 2,
-};
-assert_compile(lengthof(_housetype_cargo_mail) == HOUSE_MAX);
-
-static const byte _housetype_cargo_goods[] = {
-	 4, 4, 1, 0, 6, 6, 0, 2,
-	 2, 0, 0, 0, 0, 4, 3, 3,
-	 3, 6, 8, 6, 0, 0, 0, 0,
-	 0, 0, 0, 2, 3, 3, 3, 2,
-	 0, 0, 0, 0, 2, 0, 0, 2,
-	 3, 3, 3, 3, 0, 0, 0, 0,
-	 0, 0, 4, 4, 4, 4, 5, 5,
-	 0, 0, 0, 0, 0, 0, 0, 0,
-	 3, 3, 0, 2, 0, 2, 3, 3,
-	 4, 4, 2, 2, 2, 2, 0, 0,
-	 0, 0, 1, 0, 0, 1, 1, 4,
-	 4, 1, 4, 0, 2, 1, 2, 2,
-	 2, 2, 2, 2, 2, 2, 1, 1,
-	 0, 0, 2, 2, 2, 0
-};
-assert_compile(lengthof(_housetype_cargo_goods) == HOUSE_MAX);
-
-static const byte _housetype_cargo_food[] = {
-	 0, 0, 0, 0, 0, 0, 0, 0,
-	 0, 0, 0, 0, 0, 0, 0, 0,
-	 0, 0, 0, 0, 0, 0, 0, 0,
-	 0, 0, 0, 0, 0, 0, 0, 0,
-	 0, 0, 0, 0, 0, 1, 1, 0,
-	 0, 0, 0, 0, 2, 2, 2, 2,
-	 2, 2, 0, 0, 0, 0, 0, 0,
-	 1, 1, 1, 1, 0, 0, 1, 1,
-	 0, 0, 3, 0, 3, 0, 0, 0,
-	 0, 0, 0, 0, 0, 0, 2, 2,
-	 2, 1, 0, 0, 2, 0, 0, 0,
-	 0, 0, 0, 0, 0, 0, 0, 0,
-	 0, 0, 0, 0, 0, 0, 0, 0,
-	 4, 4, 0, 0, 0, 4
-};
-assert_compile(lengthof(_housetype_cargo_food) == HOUSE_MAX);
-
-static const byte _house_more_flags[] = {
-	  8,  8,  8,  8,  8,  8,  8, 12,
-	  0,  8,  8,  8,  8,  8,  8,  8,
-	  8,  8,  8,  8, 15,  0,  0,  0,
-	  8,  8,  8,  8,  8,  8,  8,  8,
-	 15,  0,  0,  0,  8,  8,  8,  8,
-	 15,  0,  0,  0,  8,  8,  8,  8,
-	  8,  8,  8,  8,  8,  8,  8,  8,
-	  8,  8,  8,  8,  8,  8,  8,  8,
-	  8,  8, 12,  0, 12,  0,  8,  8,
-	  8,  8, 10,  0, 10,  0,  8,  8,
-	  8,  8,  8,  8,  8,  8,  8, 10,
-	  0,  8,  8,  8,  8,  8,  8,  8,
-	  8,  8,  8, 12,  0,  8,  8,  8,
-	  8,  8,  8,  8,  8,  8,
-};
-assert_compile(lengthof(_house_more_flags) == HOUSE_MAX);
+#undef M
+assert_compile(lengthof(_original_house_specs) == NEW_HOUSE_OFFSET);
--- a/src/town.h	Mon Mar 19 12:38:16 2007 +0000
+++ b/src/town.h	Mon Mar 19 12:49:55 2007 +0000
@@ -6,9 +6,72 @@
 #include "oldpool.h"
 #include "player.h"
 #include "economy_new.h"
+#include "functions.h"
+#include "helpers.hpp"
 
 enum {
-	INVALID_TOWN = 0xFFFF,
+	HOUSE_NO_CLASS   = 0,
+	NEW_HOUSE_OFFSET = 110,
+	HOUSE_MAX        = 512,
+	INVALID_TOWN     = 0xFFFF,
+	INVALID_HOUSE_ID = 0xFFFF,
+
+	/* There can only be as many classes as there are new houses, plus one for
+	 * NO_CLASS, as the original houses don't have classes. */
+	HOUSE_CLASS_MAX  = HOUSE_MAX - NEW_HOUSE_OFFSET + 1,
+};
+
+enum BuildingFlags {
+	TILE_NO_FLAG         =       0,
+	TILE_SIZE_1x1        = 1U << 0,
+	TILE_NOT_SLOPED      = 1U << 1,
+	TILE_SIZE_2x1        = 1U << 2,
+	TILE_SIZE_1x2        = 1U << 3,
+	TILE_SIZE_2x2        = 1U << 4,
+	BUILDING_IS_ANIMATED = 1U << 5,
+	BUILDING_IS_CHURCH   = 1U << 6,
+	BUILDING_IS_STADIUM  = 1U << 7,
+	BUILDING_HAS_1_TILE  = TILE_SIZE_1x1 | TILE_SIZE_2x1 | TILE_SIZE_1x2 | TILE_SIZE_2x2,
+	BUILDING_2_TILES_X   = TILE_SIZE_2x1 | TILE_SIZE_2x2,
+	BUILDING_2_TILES_Y   = TILE_SIZE_1x2 | TILE_SIZE_2x2,
+	BUILDING_HAS_4_TILES = TILE_SIZE_2x2,
+};
+
+DECLARE_ENUM_AS_BIT_SET(BuildingFlags)
+
+enum HouseZones {                  ///< Bit  Value       Meaning
+	HZ_NOZNS             = 0x0000,  ///<       0          This is just to get rid of zeros, meaning none
+	HZ_ZON1              = 0x0001,  ///< 0..4 1,2,4,8,10  which town zones the building can be built in, Zone1 been the further suburb
+	HZ_ZON2              = 0x0002,
+	HZ_ZON3              = 0x0004,
+	HZ_ZON4              = 0x0008,
+	HZ_ZON5              = 0x0010,  ///<                  center of town
+	HZ_ZONALL            = 0x001F,  ///<       1F         This is just to englobe all above types at once
+	HZ_SUBARTC_ABOVE     = 0x0800,  ///< 11    800        can appear in sub-arctic climate above the snow line
+	HZ_TEMP              = 0x1000,  ///< 12   1000        can appear in temperate climate
+	HZ_SUBARTC_BELOW     = 0x2000,  ///< 13   2000        can appear in sub-arctic climate below the snow line
+	HZ_SUBTROPIC         = 0x4000,  ///< 14   4000        can appear in subtropical climate
+	HZ_TOYLND            = 0x8000   ///< 15   8000        can appear in toyland climate
+};
+
+DECLARE_ENUM_AS_BIT_SET(HouseZones)
+
+enum HouseExtraFlags {
+	NO_EXTRA_FLAG            =       0,
+	BUILDING_IS_HISTORICAL   = 1U << 0,  ///< this house will only appear during town generation in random games, thus the historical
+	BUILDING_IS_PROTECTED    = 1U << 1,  ///< towns and AI will not remove this house, while human players will be able tp
+	SYNCHRONISED_CALLBACK_1B = 1U << 2,  ///< synchronized callback 1B will be performed, on multi tile houses
+	CALLBACK_1A_RANDOM_BITS  = 1U << 3,  ///< callback 1A needs random bits
+};
+
+DECLARE_ENUM_AS_BIT_SET(HouseExtraFlags)
+
+typedef uint16 HouseID;
+typedef uint16 HouseClassID;
+
+struct BuildingCounts {
+	uint8 id_count[HOUSE_MAX];
+	uint8 class_count[HOUSE_CLASS_MAX];
 };
 
 struct Town : EconomicObject {
@@ -80,6 +143,9 @@
 	// NOSAVE: UpdateTownRadius updates this given the house count.
 	uint16 radius[5];
 
+	// NOSAVE: The number of each type of building in the town.
+	BuildingCounts building_counts;
+
 	/**
 	 * Sets the economic activity level of a town
 	 * @param level The activity level
@@ -138,6 +204,43 @@
 	}
 };
 
+struct HouseSpec {
+	/* Standard properties */
+	Year min_date;                     ///< introduction year of the house
+	Year max_date;                     ///< last year it can be built
+	byte population;                   ///< population (Zero on other tiles in multi tile house.)
+	byte removal_cost;                 ///< cost multiplier for removing it
+	StringID building_name;            ///< building name
+	uint16 remove_rating_decrease;     ///< rating decrease if removed
+	byte mail_generation;              ///< mail generation multiplier (tile based, as the acceptances below)
+	byte passenger_acceptance;         ///< passenger acceptance, given in 1/8th unit, max is 8, as the 3 next properies
+	byte mail_acceptance;              ///< mail acceptance
+	byte goods_acceptance;             ///< good acceptance
+	byte food_acceptance;              ///< food (or fizzy drink) acceptance
+	BuildingFlags building_flags;      ///< some flags that describe the house (size, stadium etc...)
+	HouseZones building_availability;  ///< where can it be built (climates, zones)
+	bool enabled;                      ///< the house is still avaible (by default, true.newgrf can disable it, though)
+
+	/* NewHouses properties */
+	HouseID substitute_id;             ///< which house this one is based on
+	struct SpriteGroup *spritegroup;   ///< pointer to the different sprites of the house
+	HouseID override;                  ///< which house this one replaces
+	uint16 callback_mask;              ///< House callback flags
+	byte random_colour[4];             ///< 4 "random" colours
+	byte probability;                  ///< Relative probability of appearing (16 is the standard value)
+	HouseExtraFlags extra_flags;       ///< some more flags
+	HouseClassID class_id;             ///< defines the class this house has (grf file based) @See HouseGetVariable, prop 0x44
+	byte animation_frames;             ///< number of animation frames
+	byte animation_speed;              ///< amount of time between each of those frames
+	byte processing_time;              ///< Periodic refresh multiplier
+
+	/* grf file related properties*/
+	uint8 local_id;                    ///< id defined by the grf file for this house
+	const struct GRFFile *grffile;     ///< grf file that introduced this house
+};
+
+VARDEF HouseSpec _house_specs[HOUSE_MAX];
+
 uint32 GetWorldPopulation();
 
 void UpdateTownVirtCoord(Town *t);
@@ -216,6 +319,12 @@
 
 DECLARE_OLD_POOL(Town, Town, 3, 8000)
 
+static inline HouseSpec *GetHouseSpecs(HouseID house_id)
+{
+	assert(house_id < HOUSE_MAX);
+	return &_house_specs[house_id];
+}
+
 /**
  * Check if a Town really exists.
  */
@@ -287,4 +396,9 @@
 VARDEF Town *_cleared_town;
 VARDEF int _cleared_town_rating;
 
+uint OriginalTileRandomiser(uint x, uint y);
+void ResetHouses();
+
+void ClearTownHouse(Town *t, TileIndex tile);
+
 #endif /* TOWN_H */
--- a/src/town_cmd.cpp	Mon Mar 19 12:38:16 2007 +0000
+++ b/src/town_cmd.cpp	Mon Mar 19 12:49:55 2007 +0000
@@ -5,6 +5,7 @@
 #include "stdafx.h"
 #include "openttd.h"
 #include "functions.h"
+#include "debug.h"
 #include "strings.h"
 #include "road_map.h"
 #include "table/strings.h"
@@ -19,6 +20,7 @@
 #include "gfx.h"
 #include "industry.h"
 #include "station.h"
+#include "vehicle.h"
 #include "player.h"
 #include "news.h"
 #include "saveload.h"
@@ -33,6 +35,9 @@
 #include "table/town_land.h"
 #include "genworld.h"
 #include "economy_new.h"
+#include "newgrf.h"
+#include "newgrf_callbacks.h"
+#include "newgrf_house.h"
 
 /**
  * Called if a new block is added to the town-pool
@@ -92,7 +97,6 @@
 static int _grow_town_result;
 
 static bool BuildTownHouse(Town *t, TileIndex tile);
-static void ClearTownHouse(Town *t, TileIndex tile);
 static void DoBuildTownHouse(Town *t, TileIndex tile);
 
 static void TownDrawHouseLift(const TileInfo *ti)
@@ -105,24 +109,31 @@
 	TownDrawHouseLift
 };
 
+uint OriginalTileRandomiser(uint x, uint y)
+{
+	uint variant;
+	variant  = x >> 4;
+	variant ^= x >> 6;
+	variant ^= y >> 4;
+	variant -= y >> 6;
+	variant &= 3;
+	return variant;
+}
 
 static void DrawTile_Town(TileInfo *ti)
 {
 	const DrawBuildingsTileStruct *dcts;
 	SpriteID image;
 	SpriteID pal;
+	HouseID house_id = GetHouseType(ti->tile);
+
+	if (house_id >= NEW_HOUSE_OFFSET) {
+		DrawNewHouseTile(ti, house_id);
+		return;
+	}
 
 	/* Retrieve pointer to the draw town tile struct */
-	{
-		/* this "randomizes" on the (up to) 4 variants of a building */
-		uint variant;
-		variant  = ti->x >> 4;
-		variant ^= ti->x >> 6;
-		variant ^= ti->y >> 4;
-		variant -= ti->y >> 6;
-		variant &= 3;
-		dcts = &_town_draw_tile_data[GetHouseType(ti->tile) << 4 | variant << 2 | GetHouseBuildingStage(ti->tile)];
-	}
+	dcts = &_town_draw_tile_data[house_id << 4 | OriginalTileRandomiser(ti->x, ti->y) << 2 | GetHouseBuildingStage(ti->tile)];
 
 	if (ti->tileh != SLOPE_FLAT) DrawFoundation(ti, ti->tileh);
 
@@ -173,18 +184,23 @@
 {
 	int pos, dest;
 
+	if (GetHouseType(tile) >= NEW_HOUSE_OFFSET) {
+		AnimateNewHouseTile(tile);
+		return;
+	}
+
 	if (_tick_counter & 3) return;
 
 	// If the house is not one with a lift anymore, then stop this animating.
 	// Not exactly sure when this happens, but probably when a house changes.
 	// Before this was just a return...so it'd leak animated tiles..
 	// That bug seems to have been here since day 1??
-	if (!(_housetype_extra_flags[GetHouseType(tile)] & 0x20)) {
+	if (!(GetHouseSpecs(GetHouseType(tile))->building_flags & BUILDING_IS_ANIMATED)) {
 		DeleteAnimatedTile(tile);
 		return;
 	}
 
-	if (!IsLiftMoving(tile)) {
+	if (!LiftHasDestination(tile)) {
 		int i;
 
 		/** Building has 6 floors, number 0 .. 6, where 1 is illegal.
@@ -271,69 +287,78 @@
 	IncHouseConstructionTick(tile);
 	if (GetHouseConstructionTick(tile) != 0) return;
 
-	IncHouseBuildingStage(tile);  /*increase construction stage of one more step*/
+	if (HASBIT(GetHouseSpecs(GetHouseType(tile))->callback_mask, CBM_CONSTRUCTION_STATE_CHANGE)) {
+		uint16 callback_res = GetHouseCallback(CBID_CONSTRUCTION_STATE_CHANGE, 0, GetHouseType(tile), GetTownByTile(tile), tile);
+		if (callback_res != CALLBACK_FAILED) ChangeHouseAnimationFrame(tile, callback_res);
+	}
 
-	if (GetHouseBuildingStage(tile) == TOWN_HOUSE_COMPLETED){
-		/*Now, construction is completed.  Can add population of building to the town*/
-		ChangePopulation(GetTownByTile(tile), _housetype_population[GetHouseType(tile)]);
+	if (IsHouseCompleted(tile)) {
+		/* Now that construction is complete, we can add the population of the
+		 * building to the town. */
+		ChangePopulation(GetTownByTile(tile), GetHouseSpecs(GetHouseType(tile))->population);
 	}
 	MarkTileDirtyByTile(tile);
 }
 
 static void MakeTownHouseBigger(TileIndex tile)
 {
-	uint flags = _house_more_flags[GetHouseType(tile)];
-	if (flags & 8) MakeSingleHouseBigger(TILE_ADDXY(tile, 0, 0));
-	if (flags & 4) MakeSingleHouseBigger(TILE_ADDXY(tile, 0, 1));
-	if (flags & 2) MakeSingleHouseBigger(TILE_ADDXY(tile, 1, 0));
-	if (flags & 1) MakeSingleHouseBigger(TILE_ADDXY(tile, 1, 1));
+	uint flags = GetHouseSpecs(GetHouseType(tile))->building_flags;
+	if (flags & BUILDING_HAS_1_TILE)  MakeSingleHouseBigger(TILE_ADDXY(tile, 0, 0));
+	if (flags & BUILDING_2_TILES_Y)   MakeSingleHouseBigger(TILE_ADDXY(tile, 0, 1));
+	if (flags & BUILDING_2_TILES_X)   MakeSingleHouseBigger(TILE_ADDXY(tile, 1, 0));
+	if (flags & BUILDING_HAS_4_TILES) MakeSingleHouseBigger(TILE_ADDXY(tile, 1, 1));
 }
 
 static void TileLoop_Town(TileIndex tile)
 {
-	int house;
 	Town *t;
 	uint32 r;
+	HouseID house_id = GetHouseType(tile);
+	HouseSpec *hs = GetHouseSpecs(house_id);
 
-	if (GetHouseBuildingStage(tile) != TOWN_HOUSE_COMPLETED) {
+	/* NewHouseTileLoop returns false if Callback 21 succeeded, i.e. the house
+	 * doesn't exist any more, so don't continue here. */
+	if (house_id >= NEW_HOUSE_OFFSET && !NewHouseTileLoop(tile)) return;
+
+	if (!IsHouseCompleted(tile)) {
 		/*Construction is not completed. See if we can go further in construction*/
 		MakeTownHouseBigger(tile);
 		return;
 	}
 
-	house = GetHouseType(tile);
-	if ((_housetype_extra_flags[house] & 0x20) && !LiftHasDestination(tile) && CHANCE16(1, 2) && AddAnimatedTile(tile)) BeginLiftMovement(tile);
+	/* If the lift has a destination, it is already an animated tile. */
+	if ((hs->building_flags & BUILDING_IS_ANIMATED) && house_id < NEW_HOUSE_OFFSET && !LiftHasDestination(tile) && CHANCE16(1, 2)) AddAnimatedTile(tile);
 
 	t = GetTownByTile(tile);
 
 	r = Random();
 
 	if (GB(r, 0, 8) < (t->GetActivity() * _eco->GetActivity() * 8)) {
-		int amt = _housetype_population[house] / 8 + 1;
+		int amt = hs->population / 8 + 1;
 		t->new_max_pass += amt;
 		int moved = MoveGoodsToStation(tile, 1, 1, CT_PASSENGERS, amt);
 		t->new_act_pass += moved;
 	}
 
 	if (GB(r, 8, 8) < (t->GetActivity() * _eco->GetActivity() * 8)) {
-		int amt = _housetype_mailamount[house] / 8 + 1;
+		int amt = hs->mail_generation / 8 + 1;
 		t->new_max_pass += amt;
 		int moved = MoveGoodsToStation(tile, 1, 1, CT_PASSENGERS, amt);
 		t->new_act_pass += moved;
 	}
 
-	if (_house_more_flags[house] & 8 && HASBIT(t->flags12, TOWN_IS_FUNDED) && --t->time_until_rebuild == 0) {
+	_current_player = OWNER_TOWN;
+
+	if (hs->building_flags & BUILDING_HAS_1_TILE && HASBIT(t->flags12, TOWN_IS_FUNDED) && CanDeleteHouse(tile) && --t->time_until_rebuild == 0) {
 		t->time_until_rebuild = GB(r, 16, 6) + 130;
 
-		_current_player = OWNER_TOWN;
-
 		ClearTownHouse(t, tile);
 
 		// rebuild with another house?
 		if (GB(r, 24, 8) >= 12) DoBuildTownHouse(t, tile);
+	}
 
-		_current_player = OWNER_NONE;
-	}
+	_current_player = OWNER_NONE;
 }
 
 static void ClickTile_Town(TileIndex tile)
@@ -343,16 +368,17 @@
 
 static int32 ClearTile_Town(TileIndex tile, byte flags)
 {
-	int house, rating;
+	int rating;
 	int32 cost;
 	Town *t;
+	HouseSpec *hs = GetHouseSpecs(GetHouseType(tile));
 
 	if (flags&DC_AUTO && !(flags&DC_AI_BUILDING)) return_cmd_error(STR_2004_BUILDING_MUST_BE_DEMOLISHED);
+	if (!CanDeleteHouse(tile)) return CMD_ERROR;
 
-	house = GetHouseType(tile);
-	cost = _price.remove_house * _housetype_remove_cost[house] >> 8;
+	cost = _price.remove_house * hs->removal_cost >> 8;
 
-	rating = _housetype_remove_ratingmod[house];
+	rating = hs->remove_rating_decrease;
 	_cleared_town_rating += rating;
 	_cleared_town = t = GetTownByTile(tile);
 
@@ -373,18 +399,18 @@
 
 static void GetAcceptedCargo_Town(TileIndex tile, AcceptedCargo ac)
 {
-	byte type = GetHouseType(tile);
+	HouseSpec *hs = GetHouseSpecs(GetHouseType(tile));
 
-	ac[CT_PASSENGERS] = _housetype_cargo_passengers[type];
-	ac[CT_MAIL]       = _housetype_cargo_mail[type];
-	ac[CT_GOODS]      = _housetype_cargo_goods[type];
-	ac[CT_FOOD]       = _housetype_cargo_food[type];
+	ac[CT_PASSENGERS] = hs->passenger_acceptance;
+	ac[CT_MAIL]       = hs->mail_acceptance;
+	ac[CT_GOODS]      = hs->goods_acceptance;
+	ac[CT_FOOD]       = hs->food_acceptance;
 }
 
 static void GetTileDesc_Town(TileIndex tile, TileDesc *td)
 {
-	td->str = _town_tile_names[GetHouseType(tile)];
-	if (GetHouseBuildingStage(tile) != TOWN_HOUSE_COMPLETED) {
+	td->str = GetHouseSpecs(GetHouseType(tile))->building_name;
+	if (!IsHouseCompleted(tile)) {
 		SetDParamX(td->dparam, 0, td->str);
 		td->str = STR_2058_UNDER_CONSTRUCTION;
 	}
@@ -1198,10 +1224,11 @@
 {
 	int i;
 	uint bitmask;
-	int house;
+	HouseID house;
 	Slope slope;
 	uint z;
 	uint oneof = 0;
+	HouseSpec *hs;
 
 	// Above snow?
 	slope = GetTileSlope(tile, &z);
@@ -1220,45 +1247,63 @@
 	// bits 11-15 are used
 	// bits 5-10 are not used.
 	{
-		byte houses[lengthof(_housetype_flags)];
+		HouseID houses[HOUSE_MAX];
 		int num = 0;
+		uint cumulative_probs[HOUSE_MAX];
+		uint probability_max = 0;
 
 		// Generate a list of all possible houses that can be built.
-		for (i=0; i!=lengthof(_housetype_flags); i++) {
-			if ((~_housetype_flags[i] & bitmask) == 0)
-				houses[num++] = (byte)i;
+		for (i = 0; i < HOUSE_MAX; i++) {
+			hs = GetHouseSpecs(i);
+			if ((~hs->building_availability & bitmask) == 0 && hs->enabled) {
+				if (_have_newhouses) {
+					probability_max += hs->probability;
+					cumulative_probs[num] = probability_max;
+				}
+				houses[num++] = (HouseID)i;
+			}
 		}
 
 		for (;;) {
-			house = houses[RandomRange(num)];
+			if (_have_newhouses) {
+				uint r = RandomRange(probability_max);
+				for (i = 0; i < num; i++) if (cumulative_probs[i] >= r) break;
 
-			if (_cur_year < _housetype_years[house].min || _cur_year > _housetype_years[house].max)
-				continue;
+				house = houses[i];
+			} else {
+				house = houses[RandomRange(num)];
+			}
+
+			hs = GetHouseSpecs(house);
+
+			if (_have_newhouses) {
+				if (hs->override != 0) hs = GetHouseSpecs(hs->override);
+
+				if ((hs->extra_flags & BUILDING_IS_HISTORICAL) && !_generating_world) continue;
+
+				if (HASBIT(hs->callback_mask, CBM_HOUSE_ALLOW_CONSTRUCTION)) {
+					uint16 callback_res = GetHouseCallback(CBID_HOUSE_ALLOW_CONSTRUCTION, 0, house, t, tile);
+					if (callback_res != CALLBACK_FAILED && callback_res == 0) continue;
+				}
+			}
+
+			if (_cur_year < hs->min_date || _cur_year > hs->max_date) continue;
 
 			// Special houses that there can be only one of.
-			switch (house) {
-				case HOUSE_TEMP_CHURCH:
-				case HOUSE_ARCT_CHURCH:
-				case HOUSE_SNOW_CHURCH:
-				case HOUSE_TROP_CHURCH:
-				case HOUSE_TOY_CHURCH:
-					SETBIT(oneof, TOWN_HAS_CHURCH);
-					break;
-				case HOUSE_STADIUM:
-				case HOUSE_MODERN_STADIUM:
-					SETBIT(oneof, TOWN_HAS_STADIUM);
-					break;
-				default:
-					oneof = 0;
-					break;
+			if (hs->building_flags & BUILDING_IS_CHURCH) {
+				SETBIT(oneof, TOWN_HAS_CHURCH);
+			} else if (hs->building_flags & BUILDING_IS_STADIUM) {
+				SETBIT(oneof, TOWN_HAS_STADIUM);
+			} else {
+				oneof = 0;
 			}
 
 			if (HASBITS(t->flags12 , oneof)) continue;
 
 			// Make sure there is no slope?
-			if (_housetype_extra_flags[house] & 0x12 && slope != SLOPE_FLAT) continue;
+			if (hs->building_flags & TILE_NOT_SLOPED && slope != SLOPE_FLAT) continue;
 
-			if (_housetype_extra_flags[house] & 0x10) {
+			if (hs->building_flags & TILE_SIZE_2x2) {
 				if (CheckFree2x2Area(tile) ||
 						CheckFree2x2Area(tile += TileDiffXY(-1,  0)) ||
 						CheckFree2x2Area(tile += TileDiffXY( 0, -1)) ||
@@ -1266,14 +1311,14 @@
 					break;
 				}
 				tile += TileDiffXY(0, 1);
-			} else if (_housetype_extra_flags[house] & 4) {
+			} else if (hs->building_flags & TILE_SIZE_2x1) {
 				if (CheckBuildHouseMode(tile + TileDiffXY(1, 0), slope, 0)) break;
 
 				if (CheckBuildHouseMode(tile + TileDiffXY(-1, 0), slope, 1)) {
 					tile += TileDiffXY(-1, 0);
 					break;
 				}
-			} else if (_housetype_extra_flags[house] & 8) {
+			} else if (hs->building_flags & TILE_SIZE_1x2) {
 				if (CheckBuildHouseMode(tile + TileDiffXY(0, 1), slope, 2)) break;
 
 				if (CheckBuildHouseMode(tile + TileDiffXY(0, -1), slope, 3)) {
@@ -1287,12 +1332,13 @@
 	}
 
 	t->num_houses++;
+	IncreaseBuildingCount(t, house);
 
 	// Special houses that there can be only one of.
 	t->flags12 |= oneof;
 
 	{
-		byte construction_counter = 0, construction_stage = 0, size_flags;
+		byte construction_counter = 0, construction_stage = 0;
 
 		if (_generating_world) {
 			uint32 r = Random();
@@ -1301,13 +1347,12 @@
 			if (CHANCE16(1, 7)) construction_stage = GB(r, 0, 2);
 
 			if (construction_stage == TOWN_HOUSE_COMPLETED) {
-				ChangePopulation(t, _housetype_population[house]);
+				ChangePopulation(t, hs->population);
 			} else {
 				construction_counter = GB(r, 2, 2);
 			}
 		}
-		size_flags = GB(_housetype_extra_flags[house], 2, 3);
-		MakeTownHouse(tile, t->index, construction_counter, construction_stage, size_flags, house);
+		MakeTownHouse(tile, t->index, construction_counter, construction_stage, house, VehicleRandomBits());
 	}
 }
 
@@ -1333,60 +1378,54 @@
 	DeleteAnimatedTile(tile);
 }
 
-static void ClearTownHouse(Town *t, TileIndex tile)
+void ClearTownHouse(Town *t, TileIndex tile)
 {
-	uint house = GetHouseType(tile);
+	HouseID house = GetHouseType(tile);
 	uint eflags;
+	HouseSpec *hs;
 
 	assert(IsTileType(tile, MP_HOUSE));
 
 	// need to align the tile to point to the upper left corner of the house
 	if (house >= 3) { // house id 0,1,2 MUST be single tile houses, or this code breaks.
-		if (_housetype_extra_flags[house-1] & 0x04) {
+		if (GetHouseSpecs(house-1)->building_flags & TILE_SIZE_2x1) {
 			house--;
 			tile += TileDiffXY(-1, 0);
-		} else if (_housetype_extra_flags[house-1] & 0x18) {
+		} else if (GetHouseSpecs(house-1)->building_flags & BUILDING_2_TILES_Y) {
 			house--;
 			tile += TileDiffXY(0, -1);
-		} else if (_housetype_extra_flags[house-2] & 0x10) {
+		} else if (GetHouseSpecs(house-2)->building_flags & BUILDING_HAS_4_TILES) {
 			house-=2;
 			tile += TileDiffXY(-1, 0);
-		} else if (_housetype_extra_flags[house-3] & 0x10) {
+		} else if (GetHouseSpecs(house-3)->building_flags & BUILDING_HAS_4_TILES) {
 			house-=3;
 			tile += TileDiffXY(-1, -1);
 		}
 	}
 
+	hs = GetHouseSpecs(house);
+
 	// Remove population from the town if the house is finished.
-	if (GetHouseBuildingStage(tile) == TOWN_HOUSE_COMPLETED) {
-		ChangePopulation(t, -_housetype_population[house]);
+	if (IsHouseCompleted(tile)) {
+		ChangePopulation(t, -hs->population);
 	}
 
 	t->num_houses--;
+	DecreaseBuildingCount(t, house);
 
 	// Clear flags for houses that only may exist once/town.
-	switch (house) {
-		case HOUSE_TEMP_CHURCH:
-		case HOUSE_ARCT_CHURCH:
-		case HOUSE_SNOW_CHURCH:
-		case HOUSE_TROP_CHURCH:
-		case HOUSE_TOY_CHURCH:
-			CLRBIT(t->flags12, TOWN_HAS_CHURCH);
-			break;
-		case HOUSE_STADIUM:
-		case HOUSE_MODERN_STADIUM:
-			CLRBIT(t->flags12, TOWN_HAS_STADIUM);
-			break;
-		default:
-			break;
+	if (hs->building_flags & BUILDING_IS_CHURCH) {
+		CLRBIT(t->flags12, TOWN_HAS_CHURCH);
+	} else if (hs->building_flags & BUILDING_IS_STADIUM) {
+		CLRBIT(t->flags12, TOWN_HAS_STADIUM);
 	}
 
 	// Do the actual clearing of tiles
-	eflags = _housetype_extra_flags[house];
+	eflags = hs->building_flags;
 	DoClearTownHouseHelper(tile);
-	if (eflags & 0x14) DoClearTownHouseHelper(tile + TileDiffXY(1, 0));
-	if (eflags & 0x18) DoClearTownHouseHelper(tile + TileDiffXY(0, 1));
-	if (eflags & 0x10) DoClearTownHouseHelper(tile + TileDiffXY(1, 1));
+	if (eflags & BUILDING_2_TILES_X)   DoClearTownHouseHelper(tile + TileDiffXY(1, 0));
+	if (eflags & BUILDING_2_TILES_Y)   DoClearTownHouseHelper(tile + TileDiffXY(0, 1));
+	if (eflags & BUILDING_HAS_4_TILES) DoClearTownHouseHelper(tile + TileDiffXY(1, 1));
 }
 
 /** Rename a town (server-only).
@@ -1935,6 +1974,37 @@
 	SLE_END()
 };
 
+/* Save and load the mapping between the house id on the map, and the grf file
+ * it came from. */
+static const SaveLoad _house_id_mapping_desc[] = {
+	SLE_VAR(HouseIDMapping, grfid,         SLE_UINT32),
+	SLE_VAR(HouseIDMapping, house_id,      SLE_UINT8),
+	SLE_VAR(HouseIDMapping, substitute_id, SLE_UINT8),
+	SLE_END()
+};
+
+static void Save_HOUSEIDS()
+{
+	uint i;
+
+	for (i = 0; i != lengthof(_house_id_mapping); i++) {
+		SlSetArrayIndex(i);
+		SlObject(&_house_id_mapping[i], _house_id_mapping_desc);
+	}
+}
+
+static void Load_HOUSEIDS()
+{
+	int index;
+
+	ResetHouseIDMapping();
+
+	while ((index = SlIterateArray()) != -1) {
+		if ((uint)index >= lengthof(_house_id_mapping)) break;
+		SlObject(&_house_id_mapping[index], _house_id_mapping_desc);
+	}
+}
+
 static void Save_TOWN()
 {
 	Town *t;
@@ -1979,7 +2049,13 @@
 	_town_sort_dirty = true;
 }
 
-
 extern const ChunkHandler _town_chunk_handlers[] = {
-	{ 'CITY', Save_TOWN, Load_TOWN, CH_ARRAY | CH_LAST},
+	{ 'HIDS', Save_HOUSEIDS, Load_HOUSEIDS, CH_ARRAY },
+	{ 'CITY', Save_TOWN,     Load_TOWN,     CH_ARRAY | CH_LAST},
 };
+
+void ResetHouses()
+{
+	memset(&_house_specs, 0, sizeof(_house_specs));
+	memcpy(&_house_specs, &_original_house_specs, sizeof(_original_house_specs));
+}
--- a/src/town_map.h	Mon Mar 19 12:38:16 2007 +0000
+++ b/src/town_map.h	Mon Mar 19 12:49:55 2007 +0000
@@ -6,7 +6,14 @@
 #define TOWN_MAP_H
 
 #include "town.h"
+#include "date.h"
 
+/**
+ * Get the index of which town this house/street is attached to.
+ * @param t the tile
+ * @pre IsTileType(t, MP_HOUSE) or IsTileType(t, MP_STREET)
+ * @return TownID
+ */
 static inline TownID GetTownIndex(TileIndex t)
 {
 	assert(IsTileType(t, MP_HOUSE) || IsTileType(t, MP_STREET)); // XXX incomplete
@@ -15,13 +22,14 @@
 
 /**
  * Set the town index for a road or house tile.
- * @param tile the tile
+ * @param t the tile
+ * @pre IsTileType(t, MP_HOUSE) or IsTileType(t, MP_STREET)
  * @param index the index of the town
  * @pre IsTileType(t, MP_STREET) || IsTileType(t, MP_HOUSE)
  */
 static inline void SetTownIndex(TileIndex t, TownID index)
 {
-	assert(IsTileType(t, MP_STREET) || IsTileType(t, MP_HOUSE));
+	assert(IsTileType(t, MP_HOUSE) || IsTileType(t, MP_STREET));
 	_m[t].m2 = index;
 }
 
@@ -35,84 +43,189 @@
 	return GetTown(GetTownIndex(t));
 }
 
-
-static inline int GetHouseType(TileIndex t)
+/**
+ * Get the type of this house, which is an index into the house spec array
+ * Since m4 is only a byte and we want to support 512 houses, we use the bit 6
+ * of m3 as an additional bit to house type.
+ * @param t the tile
+ * @pre IsTileType(t, MP_HOUSE)
+ * @return house type
+ */
+static inline HouseID GetHouseType(TileIndex t)
 {
 	assert(IsTileType(t, MP_HOUSE));
-	return _m[t].m4;
-}
-
-static inline bool LiftHasDestination(TileIndex t)
-{
-	return HASBIT(_m[t].m5, 7);
-}
-
-static inline void SetLiftDestination(TileIndex t, byte dest)
-{
-	SB(_m[t].m5, 0, 6, dest);
-	SETBIT(_m[t].m1, 7); /* Start moving */
+	return _m[t].m4 | (GB(_m[t].m3, 6, 1) << 8);
 }
 
-static inline byte GetLiftDestination(TileIndex t)
+/**
+ * Set the house type.
+ * @param t the tile
+ * @param house_id the new house type
+ * @pre IsTileType(t, MP_HOUSE)
+ */
+static inline void SetHouseType(TileIndex t, HouseID house_id)
 {
-	return GB(_m[t].m5, 0, 6);
-}
-
-static inline bool IsLiftMoving(TileIndex t)
-{
-	return HASBIT(_m[t].m1, 7);
+	assert(IsTileType(t, MP_HOUSE));
+	_m[t].m4 = GB(house_id, 0, 8);
+	SB(_m[t].m3, 6, 1, GB(house_id, 8, 1));
 }
 
-static inline void BeginLiftMovement(TileIndex t)
+/**
+ * Check if the lift of this animated house has a destination
+ * @param t the tile
+ * @return has destination
+ */
+static inline bool LiftHasDestination(TileIndex t)
 {
-	SETBIT(_m[t].m5, 7);
+	return HASBIT(_me[t].m7, 0);
 }
 
+/**
+ * Set the new destination of the lift for this animated house, and activate
+ * the LiftHasDestination bit.
+ * @param t the tile
+ * @param dest new destination
+ */
+static inline void SetLiftDestination(TileIndex t, byte dest)
+{
+	SETBIT(_me[t].m7, 0);
+	SB(_me[t].m7, 1, 3, dest);
+}
+
+/**
+ * Get the current destination for this lift
+ * @param t the tile
+ * @return destination
+ */
+static inline byte GetLiftDestination(TileIndex t)
+{
+	return GB(_me[t].m7, 1, 3);
+}
+
+/**
+ * Stop the lift of this animated house from moving.
+ * Clears the first 4 bits of m7 at once, clearing the LiftHasDestination bit
+ * and the destination.
+ * @param t the tile
+ */
 static inline void HaltLift(TileIndex t)
 {
-	CLRBIT(_m[t].m1, 7);
-	CLRBIT(_m[t].m5, 7);
-	SB(_m[t].m5, 0, 6, 0);
-
+	SB(_me[t].m7, 0, 4, 0);
 	DeleteAnimatedTile(t);
 }
 
+/**
+ * Get the position of the lift on this animated house
+ * @param t the tile
+ * @return position, from 0 to 36
+ */
 static inline byte GetLiftPosition(TileIndex t)
 {
-	return GB(_m[t].m1, 0, 7);
+	return GB(_m[t].m6, 2, 6);
 }
 
+/**
+ * Set the position of the lift on this animated house
+ * @param t the tile
+ * @param pos, from 0 to 36
+ */
 static inline void SetLiftPosition(TileIndex t, byte pos)
 {
-	SB(_m[t].m1, 0, 7, pos);
+	SB(_m[t].m6, 2, 6, pos);
 }
 
-static inline void MakeHouseTile(TileIndex t, TownID tid, byte counter, byte stage, byte type)
+/**
+ * Get the current animation frame for this house
+ * @param t the tile
+ * @pre IsTileType(t, MP_HOUSE)
+ * @return frame number
+ */
+static inline byte GetHouseAnimationFrame(TileIndex t)
+{
+	assert(IsTileType(t, MP_HOUSE));
+	return GB(_m[t].m6, 3, 5);
+}
+
+/**
+ * Set a new animation frame for this house
+ * @param t the tile
+ * @param frame the new frame number
+ * @pre IsTileType(t, MP_HOUSE)
+ */
+static inline void SetHouseAnimationFrame(TileIndex t, byte frame)
+{
+	assert(IsTileType(t, MP_HOUSE));
+	SB(_m[t].m6, 3, 5, frame);
+}
+
+/**
+ * Get the completion of this house
+ * @param t the tile
+ * @return true if it is, false if it is not
+ */
+static inline bool IsHouseCompleted(TileIndex t)
+{
+	assert(IsTileType(t, MP_HOUSE));
+	return HASBIT(_m[t].m3, 7);
+}
+
+/**
+ * Mark this house as been completed
+ * @param t the tile
+ * @param status
+ */
+static inline void SetHouseCompleted(TileIndex t, bool status)
+{
+	assert(IsTileType(t, MP_HOUSE));
+	SB(_m[t].m3, 7, 1, !!status);
+}
+
+/**
+ * Make the tile a house.
+ * @param t tile index
+ * @param tid Town index
+ * @param counter of construction step
+ * @param stage of construction (used for drawing)
+ * @param type of house.  Index into house specs array
+ * @param random_bits required for newgrf houses
+ * @pre IsTileType(t, MP_CLEAR)
+ */
+static inline void MakeHouseTile(TileIndex t, TownID tid, byte counter, byte stage, HouseID type, byte random_bits)
 {
 	assert(IsTileType(t, MP_CLEAR));
 
 	SetTileType(t, MP_HOUSE);
-	_m[t].m1 = 0;
+	_m[t].m1 = random_bits;
 	_m[t].m2 = tid;
-	SB(_m[t].m3, 6, 2, stage);
-	_m[t].m4 = type;
-	SB(_m[t].m5, 0, 2, counter);
+	_m[t].m3 = 0;
+	SetHouseType(t, type);
+	SetHouseCompleted(t, stage == TOWN_HOUSE_COMPLETED);
+	_m[t].m5 = IsHouseCompleted(t) ? 0 : (stage << 3 | counter);
+	SetHouseAnimationFrame(t, 0);
+	_me[t].m7 = GetHouseSpecs(type)->processing_time;
 
+	if (GetHouseSpecs(type)->building_flags & BUILDING_IS_ANIMATED) AddAnimatedTile(t);
 	MarkTileDirtyByTile(t);
 }
 
-enum {
-	TWO_BY_TWO_BIT = 2, ///< House is two tiles in X and Y directions
-	ONE_BY_TWO_BIT = 1, ///< House is two tiles in Y direction
-	TWO_BY_ONE_BIT = 0, ///< House is two tiles in X direction
-};
-
-static inline void MakeTownHouse(TileIndex t, TownID tid, byte counter, byte stage, byte size, byte type)
+/**
+ * Helper function for MakeHouseTile.
+ * It is called  for each tile of a multi-tile house.
+ * Parametes are the same.
+ * @param t tile index
+ * @param tid Town index
+ * @param counter of construction step
+ * @param stage of construction (used for drawing)
+ * @param type of house.  Index into house specs array
+ * @param random_bits required for newgrf houses
+ */
+static inline void MakeTownHouse(TileIndex t, TownID tid, byte counter, byte stage, HouseID type, byte random_bits)
 {
-	MakeHouseTile(t, tid, counter, stage, type);
-	if (HASBIT(size, TWO_BY_TWO_BIT) || HASBIT(size, ONE_BY_TWO_BIT)) MakeHouseTile(t + TileDiffXY(0, 1), tid, counter, stage, ++type);
-	if (HASBIT(size, TWO_BY_TWO_BIT) || HASBIT(size, TWO_BY_ONE_BIT)) MakeHouseTile(t + TileDiffXY(1, 0), tid, counter, stage, ++type);
-	if (HASBIT(size, TWO_BY_TWO_BIT)) MakeHouseTile(t + TileDiffXY(1, 1), tid, counter, stage, ++type);
+	BuildingFlags size = GetHouseSpecs(type)->building_flags;
+	MakeHouseTile(t, tid, counter, stage, type, random_bits);
+	if (size & BUILDING_2_TILES_Y)   MakeHouseTile(t + TileDiffXY(0, 1), tid, counter, stage, ++type, random_bits);
+	if (size & BUILDING_2_TILES_X)   MakeHouseTile(t + TileDiffXY(1, 0), tid, counter, stage, ++type, random_bits);
+	if (size & BUILDING_HAS_4_TILES) MakeHouseTile(t + TileDiffXY(1, 1), tid, counter, stage, ++type, random_bits);
 }
 
 /**
@@ -120,81 +233,143 @@
  *  Construction counter, for buildings under construction. Incremented on every
  *  periodic tile processing.
  *  On wraparound, the stage of building in is increased.
- *  (Get|Set|Inc)HouseBuildingStage are taking care of the real stages,
+ *  GetHouseBuildingStage is taking care of the real stages,
  *  (as the sprite for the next phase of house building)
- *  (Get|Set|Inc)HouseConstructionTick is simply a tick counter between the
+ *  (Get|Inc)HouseConstructionTick is simply a tick counter between the
  *  different stages
  */
 
 /**
  * Gets the building stage of a house
- * @param tile the tile of the house to get the building stage of
+ * Since the stage is used for determining what sprite to use,
+ * if the house is complete (and that stage no longuer is available),
+ * fool the system by returning the TOWN_HOUSE_COMPLETE (3),
+ * thus showing a beautiful complete house.
+ * @param t the tile of the house to get the building stage of
  * @pre IsTileType(t, MP_HOUSE)
  * @return the building stage of the house
  */
 static inline byte GetHouseBuildingStage(TileIndex t)
 {
 	assert(IsTileType(t, MP_HOUSE));
-	return GB(_m[t].m3, 6, 2);
-}
-
-/**
- * Sets the building stage of a house
- * @param tile the tile of the house to set the building stage of
- * @param stage the new stage
- * @pre IsTileType(t, MP_HOUSE)
- */
-static inline void SetHouseBuildingStage(TileIndex t, byte stage)
-{
-	assert(IsTileType(t, MP_HOUSE));
-	SB(_m[t].m3, 6, 2, stage);
-}
-
-/**
- * Increments the building stage of a house
- * @param tile the tile of the house to increment the building stage of
- * @pre IsTileType(t, MP_HOUSE)
- */
-static inline void IncHouseBuildingStage( TileIndex t )
-{
-	assert(IsTileType(t, MP_HOUSE));
-	AB(_m[t].m3, 6, 2, 1);
+	return IsHouseCompleted(t) ? (byte)TOWN_HOUSE_COMPLETED : GB(_m[t].m5, 3, 2);
 }
 
 /**
  * Gets the construction stage of a house
- * @param tile the tile of the house to get the construction stage of
+ * @param t the tile of the house to get the construction stage of
  * @pre IsTileType(t, MP_HOUSE)
  * @return the construction stage of the house
  */
 static inline byte GetHouseConstructionTick(TileIndex t)
 {
 	assert(IsTileType(t, MP_HOUSE));
-	return GB(_m[t].m5, 0, 3);
-}
-
-/**
- * Sets the construction stage of a house
- * @param tile the tile of the house to set the construction stage of
- * @param stage the new stage
- * @pre IsTileType(t, MP_HOUSE)
- */
-static inline void SetHouseConstructionTick(TileIndex t, byte stage)
-{
-	assert(IsTileType(t, MP_HOUSE));
-	SB(_m[t].m5, 0, 3, stage);
+	return IsHouseCompleted(t) ? 0 : GB(_m[t].m5, 0, 3);
 }
 
 /**
  * Sets the increment stage of a house
- * @param tile the tile of the house to increment the construction stage of
+ * It is working with the whole counter + stage 5 bits, making it
+ * easier to work:  the wraparound is automatic.
+ * @param t the tile of the house to increment the construction stage of
  * @pre IsTileType(t, MP_HOUSE)
  */
 static inline void IncHouseConstructionTick(TileIndex t)
 {
 	assert(IsTileType(t, MP_HOUSE));
-	AB(_m[t].m5, 0, 3, 1);
+	AB(_m[t].m5, 0, 5, 1);
+
+	if (GB(_m[t].m5, 3, 2) == TOWN_HOUSE_COMPLETED) {
+		/* House is now completed.
+		 * Store the year of construction as well, for newgrf house purpose */
+		SetHouseCompleted(t, true);
+		_m[t].m5 = clamp(_cur_year - ORIGINAL_BASE_YEAR, 0, 0xFF);
+	}
 }
 
+/**
+ * Get the year that this house was constructed (between 1920 and 2175).
+ * @param t the tile of this house
+ * @pre IsTileType(t, MP_HOUSE)
+ * @return year
+ */
+static inline Year GetHouseConstructionYear(TileIndex t)
+{
+	assert(IsTileType(t, MP_HOUSE));
+	return IsHouseCompleted(t) ? _m[t].m5 + ORIGINAL_BASE_YEAR : 0;
+}
+
+/**
+ * Get the random bits for this house.
+ * This is required for newgrf house
+ * @param t the tile of this house
+ * @pre IsTileType(t, MP_HOUSE)
+ * @return random bits
+ */
+static inline byte GetHouseRandomBits(TileIndex t)
+{
+	assert(IsTileType(t, MP_HOUSE));
+	return _m[t].m1;
+}
+
+/**
+ * Set the activated triggers bits for this house.
+ * This is required for newgrf house
+ * @param t the tile of this house
+ * @pre IsTileType(t, MP_HOUSE)
+ */
+static inline void SetHouseTriggers(TileIndex t, byte triggers)
+{
+	assert(IsTileType(t, MP_HOUSE));
+	SB(_m[t].m3, 0, 5, triggers);
+}
+
+/**
+ * Get the already activated triggers bits for this house.
+ * This is required for newgrf house
+ * @param t the tile of this house
+ * @pre IsTileType(t, MP_HOUSE)
+ * @return triggers
+ */
+static inline byte GetHouseTriggers(TileIndex t)
+{
+	assert(IsTileType(t, MP_HOUSE));
+	return GB(_m[t].m3, 0, 5);
+}
+
+/**
+ * Get the amount of time remaining before the tile loop processes this tile.
+ * @param t the house tile
+ * @pre IsTileType(t, MP_HOUSE)
+ * @return time remaining
+ */
+static inline byte GetHouseProcessingTime(TileIndex t)
+{
+	assert(IsTileType(t, MP_HOUSE));
+	return _me[t].m7;
+}
+
+/**
+ * Set the amount of time remaining before the tile loop processes this tile.
+ * @param t the house tile
+ * @param time the time to be set
+ * @pre IsTileType(t, MP_HOUSE)
+ */
+static inline void SetHouseProcessingTime(TileIndex t, byte time)
+{
+	assert(IsTileType(t, MP_HOUSE));
+	_me[t].m7 = time;
+}
+
+/**
+ * Decrease the amount of time remaining before the tile loop processes this tile.
+ * @param t the house tile
+ * @pre IsTileType(t, MP_HOUSE)
+ */
+static inline void DecHouseProcessingTime(TileIndex t)
+{
+	assert(IsTileType(t, MP_HOUSE));
+	_me[t].m7--;
+}
 
 #endif /* TOWN_MAP_H */
--- a/src/train_cmd.cpp	Mon Mar 19 12:38:16 2007 +0000
+++ b/src/train_cmd.cpp	Mon Mar 19 12:49:55 2007 +0000
@@ -2815,7 +2815,7 @@
 {
 	uint num = 0;
 	BEGIN_ENUM_WAGONS(v)
-		if (v->cargo_type == CT_PASSENGERS) num += v->cargo_count;
+		if (IsCargoInClass(v->cargo_type, CC_PASSENGERS)) num += v->cargo_count;
 	END_ENUM_WAGONS(v)
 	return num;
 }
--- a/src/void_map.h	Mon Mar 19 12:38:16 2007 +0000
+++ b/src/void_map.h	Mon Mar 19 12:49:55 2007 +0000
@@ -13,6 +13,7 @@
 	_m[t].m4 = 0;
 	_m[t].m5 = 0;
 	_m[t].m6 = 0;
+	_me[t].m7 = 0;
 }
 
 #endif /* VOID_MAP_H */
--- a/src/water_cmd.cpp	Mon Mar 19 12:38:16 2007 +0000
+++ b/src/water_cmd.cpp	Mon Mar 19 12:49:55 2007 +0000
@@ -614,8 +614,7 @@
 
 		if (v->type == VEH_ROAD) { // flood bus/truck
 			pass = 1; // driver
-			if (v->cargo_type == CT_PASSENGERS)
-				pass += v->cargo_count;
+			if (IsCargoInClass(v->cargo_type, CC_PASSENGERS)) pass += v->cargo_count;
 
 			v->vehstatus |= VS_CRASHED;
 			v->u.road.crashed_ctr = 2000; // max 2220, disappear pretty fast
@@ -629,7 +628,7 @@
 
 			// crash all wagons, and count passangers
 			BEGIN_ENUM_WAGONS(v)
-				if (v->cargo_type == CT_PASSENGERS) pass += v->cargo_count;
+				if (IsCargoInClass(v->cargo_type, CC_PASSENGERS)) pass += v->cargo_count;
 				v->vehstatus |= VS_CRASHED;
 				MarkAllViewportsDirty(v->left_coord, v->top_coord, v->right_coord + 1, v->bottom_coord + 1);
 			END_ENUM_WAGONS(v)