initial commit, lordsawar source, slightly modified
[lordsawar] / src / GraphicsCache.cpp
1 // Copyright (C) 2003, 2004, 2005, 2006, 2007 Ulf Lorenz
2 // Copyright (C) 2004, 2005, 2006 Andrea Paternesi
3 // Copyright (C) 2006, 2007, 2008, 2009 Ben Asselstine
4 //
5 //  This program is free software; you can redistribute it and/or modify
6 //  it under the terms of the GNU General Public License as published by
7 //  the Free Software Foundation; either version 3 of the License, or
8 //  (at your option) any later version.
9 //
10 //  This program is distributed in the hope that it will be useful,
11 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 //  GNU Library General Public License for more details.
14 //
15 //  You should have received a copy of the GNU General Public License
16 //  along with this program; if not, write to the Free Software
17 //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 
18 //  02110-1301, USA.
19
20 #include <assert.h>
21 #include <string.h>
22
23 #include "rectangle.h"
24
25 #include "GraphicsCache.h"
26 #include "armysetlist.h"
27 #include "shieldsetlist.h"
28 #include "tilesetlist.h"
29 #include "citysetlist.h"
30 #include "citylist.h"
31 #include "army.h"
32 #include "playerlist.h"
33 #include "Configuration.h"
34 #include "File.h"
35 #include "GameMap.h"
36 #include "city.h"
37 #include "stack.h"
38 #include "gui/image-helpers.h"
39 #include "FogMap.h"
40 #include "hero.h"
41
42 //#define debug(x) {std::cerr<<__FILE__<<": "<<__LINE__<<": "<<x<<std::endl<<std::flush;}
43 #define debug(x)
44
45 //some structures first
46
47 //this structure is the base class for storing cached objects. It stores the
48 //(army-, but can be extended) set, the type of army and the player which the
49 //surface is designed for (and the surface itself, of course).
50 struct ArmyCacheItem
51 {
52     guint32 armyset;
53     guint32 army_id;
54     guint32 player_id;
55     bool medals[3];
56     bool greyed;
57     PixMask* surface;
58 };
59 bool operator <(ArmyCacheItem lhs, ArmyCacheItem rhs)
60 {
61   return memcmp(&lhs, &rhs, sizeof (ArmyCacheItem) - sizeof (PixMask*)) < 0;
62 }
63
64 //the structure to store ships in
65 struct ShipCacheItem
66 {
67     guint32 player_id;
68     guint32 armyset;
69     PixMask* surface;
70 };
71
72 //the structure to store planted standard in
73 struct PlantedStandardCacheItem
74 {
75     guint32 player_id;
76     guint32 armyset;
77     PixMask* surface;
78 };
79
80 //the structure to store new level pictures in
81 struct NewLevelCacheItem
82 {
83     guint32 player_id;
84     guint32 gender;
85     PixMask* surface;
86 };
87
88 //the structure to store temples in
89 struct TempleCacheItem
90 {
91     guint32 cityset;
92     int type;
93     PixMask* surface;
94 };
95
96 //the structure to store ruins in
97 struct RuinCacheItem
98 {
99     guint32 cityset;
100     int type;
101     PixMask* surface;
102 };
103
104 //the structure to store diplomacy icons in
105 struct DiplomacyCacheItem
106 {
107     int type;
108     Player::DiplomaticState state;
109     PixMask* surface;
110 };
111
112 //the structure to store roads in
113 struct RoadCacheItem
114 {
115     guint32 tileset;
116     int type;
117     PixMask* surface;
118 };
119
120 //the structure to store fog patterns in
121 struct FogCacheItem
122 {
123     guint32 tileset;
124     int type;
125     PixMask* surface;
126 };
127 bool operator <(FogCacheItem lhs, FogCacheItem rhs)
128 {
129   return memcmp(&lhs, &rhs, sizeof (FogCacheItem) - sizeof (PixMask*)) < 0;
130 }
131
132 //the structure to store bridges in
133 struct BridgeCacheItem
134 {
135     guint32 tileset;
136     int type;
137     PixMask* surface;
138 };
139
140 //the structure to store cursors in
141 struct CursorCacheItem
142 {
143     int type;
144     PixMask* surface;
145 };
146
147 //the structure to store buildings in
148 struct CityCacheItem
149 {
150     guint32 cityset;
151     int type;
152     guint32 player_id;
153     PixMask* surface;
154 };
155
156 //the structure to store towers in
157 struct TowerCacheItem
158 {
159     guint32 cityset;
160     guint32 player_id;
161     PixMask* surface;
162 };
163
164 // the structure to store flags in
165 struct FlagCacheItem
166 {
167     guint32 tileset;
168     guint32 size;
169     guint32 player_id;
170     PixMask* surface;
171 };
172
173 // the structure to store selector images in
174 struct SelectorCacheItem
175 {
176     guint32 tileset;
177     guint32 type;
178     guint32 frame;
179     guint32 player_id;
180     PixMask* surface;
181 };
182
183 // the structure to store shield images in
184 struct ShieldCacheItem
185 {
186     guint32 shieldset;
187     guint32 type;
188     guint32 colour;
189     PixMask* surface;
190 };
191
192 // the structure to store production shield images in
193 struct ProdShieldCacheItem
194 {
195     guint32 type;
196     bool prod;
197     PixMask* surface;
198 };
199
200 // the structure to store movement bonus images in
201 struct MoveBonusCacheItem
202 {
203     guint32 type; // 0=empty, 1=trees, 2=foothills, 3=hills+trees, 4=fly, 5=boat
204     PixMask* surface;
205 };
206
207 // the structure to store drawn bigmap tiles in
208 struct TileCacheItem
209 {
210   int tile_style_id;
211   int fog_type_id;
212   bool has_bag;
213   bool has_standard;
214   int standard_player_id;
215   int stack_size; //flag size
216   int stack_player_id;
217   int army_type_id;
218   bool has_tower;
219   bool has_ship;
220   Maptile::Building building_type;
221   int building_subtype;
222   Vector<int> building_tile;
223   int building_player_id;
224   guint32 tilesize;
225   bool has_grid;
226   guint32 tileset;
227   guint32 cityset;
228   PixMask* surface;
229 };
230
231 struct PortCacheItem
232 {
233   guint32 cityset;
234   PixMask *surface;
235 };
236
237 struct SignpostCacheItem
238 {
239   guint32 cityset;
240   PixMask *surface;
241 };
242
243 struct BagCacheItem
244 {
245   guint32 armyset;
246   PixMask *surface;
247 };
248
249 struct ExplosionCacheItem
250 {
251   guint32 tileset;
252   PixMask *surface;
253 };
254
255 bool operator <(TileCacheItem lhs, TileCacheItem rhs)
256 {
257   return memcmp(&lhs, &rhs, sizeof (TileCacheItem) - sizeof (PixMask*)) < 0;
258 }
259 //-----------------------------------------------------
260
261 GraphicsCache* GraphicsCache::s_instance = 0;
262
263 GraphicsCache* GraphicsCache::getInstance()
264 {
265     if (!s_instance)
266         s_instance = new GraphicsCache();
267
268     return s_instance;
269 }
270
271 void GraphicsCache::deleteInstance()
272 {
273     if (!s_instance)
274         return;
275
276     delete s_instance;
277     s_instance =0;
278 }
279
280 GraphicsCache::GraphicsCache()
281     :d_cachesize(0)
282 {
283     loadDiplomacyPics();
284
285     loadCursorPics();
286     loadProdShields();
287     loadMoveBonusPics();
288     loadMedalPics();
289     loadNewLevelPics();
290
291     d_smallruinedcity = getMiscPicture("smallruinedcity.png");
292     d_smallhero = getMiscPicture("hero.png");
293     d_smallinactivehero = getMiscPicture("hero-inactive.png");
294     d_small_ruin_unexplored = getMiscPicture("smallunexploredruin.png");
295     d_small_stronghold_unexplored = 
296       getMiscPicture("smallunexploredstronghold.png");
297     d_small_ruin_explored = getMiscPicture("smallexploredruin.png");
298     d_small_temple = getMiscPicture("smalltemple.png");
299 }
300
301 GraphicsCache::~GraphicsCache()
302 {
303     clear();
304
305     for (unsigned int i = 0; i < PRODUCTION_SHIELD_TYPES; i++)
306     {
307         delete d_prodshieldpic[i];
308     }
309
310     for (unsigned int i = 0; i < MOVE_BONUS_TYPES; i++)
311     {
312         delete d_movebonuspic[i];
313     }
314
315     delete d_smallruinedcity;
316     delete d_smallhero;
317     delete d_smallinactivehero;
318     delete d_small_temple;
319     delete d_small_ruin_unexplored;
320     delete d_small_stronghold_unexplored;
321     delete d_small_ruin_explored;
322     delete d_newlevel_male;
323     delete d_newlevel_female;
324     delete d_newlevelmask_male;
325     delete d_newlevelmask_female;
326 }
327
328 PixMask* GraphicsCache::getSmallRuinedCityPic()
329 {
330   return d_smallruinedcity;
331 }
332
333 PixMask* GraphicsCache::getSmallHeroPic(bool active)
334 {
335   if (active)
336     return d_smallhero;
337   else
338     return d_smallinactivehero;
339 }
340
341 PixMask* GraphicsCache::getSmallRuinExploredPic()
342 {
343   return d_small_ruin_explored;
344 }
345 PixMask* GraphicsCache::getSmallRuinUnexploredPic()
346 {
347   return d_small_ruin_unexplored;
348 }
349 PixMask* GraphicsCache::getSmallStrongholdUnexploredPic()
350 {
351   return d_small_stronghold_unexplored;
352 }
353 PixMask* GraphicsCache::getSmallTemplePic()
354 {
355   return d_small_temple;
356 }
357
358 PixMask* GraphicsCache::getMoveBonusPic(guint32 bonus, bool has_ship)
359 {
360   guint32 type;
361   if (bonus == Tile::isFlying()) // show fly icon
362     type = 4; 
363   else if (bonus & Tile::FOREST && bonus & Tile::HILLS) // show trees and hills
364     type = 3;
365   else if (bonus & Tile::HILLS) // show foothills
366     type = 2;
367   else if (bonus & Tile::FOREST) // show trees
368     type = 1;
369   else if (has_ship) // (what a) show boat
370     type = 5;
371   else // show blank
372     type = 0;
373   debug("GraphicsCache::getMoveBonusPic " <<bonus <<"," <<type)
374
375   std::list<MoveBonusCacheItem*>::iterator it;
376   MoveBonusCacheItem* myitem;
377
378   for (it = d_movebonuslist.begin(); it != d_movebonuslist.end(); it++)
379   {
380       if ((*it)->type == type)
381       {
382           myitem = (*it);
383
384           //put the item in last place (last touched)
385           d_movebonuslist.erase(it);
386           d_movebonuslist.push_back(myitem);
387
388           return myitem->surface;
389       }
390     }
391
392     //no item found -> create a new one
393     myitem = addMoveBonusPic(type);
394
395     return myitem->surface;
396 }
397
398 PixMask* GraphicsCache::getShipPic(const Player* p)
399 {
400     debug("getting ship pic " <<p->getName())
401     std::list<ShipCacheItem*>::iterator it;
402     ShipCacheItem* myitem;
403     for (it = d_shiplist.begin(); it != d_shiplist.end(); it++)
404     {
405         if ((*it)->player_id == p->getId() && (*it)->armyset == p->getArmyset())
406         {
407             myitem = (*it);
408             
409             // put the item on the last place (==last touched)
410             d_shiplist.erase(it);
411             d_shiplist.push_back(myitem);
412             
413             return myitem->surface;
414         }
415     }
416     // We are still here, so the graphic is not in the cache. addShipPic calls
417     // checkPictures on its own, so we can simply return the surface
418     myitem = addShipPic(p);
419
420     return myitem->surface;
421 }
422
423 PixMask* GraphicsCache::getNewLevelPic(const Player* p, guint32 gender)
424 {
425     debug("getting new level pic " <<p->getName())
426     std::list<NewLevelCacheItem*>::iterator it;
427     NewLevelCacheItem* myitem;
428     for (it = d_newlevellist.begin(); it != d_newlevellist.end(); it++)
429     {
430         if ((*it)->player_id == p->getId() && (*it)->gender == gender)
431         {
432             myitem = (*it);
433             
434             // put the item on the last place (==last touched)
435             d_newlevellist.erase(it);
436             d_newlevellist.push_back(myitem);
437             
438             return myitem->surface;
439         }
440     }
441     // We are still here, so the graphic is not in the cache. 
442     // addNewLevelPic calls checkPictures on its own, so we can 
443     // simply return the surface
444     myitem = addNewLevelPic(p, gender);
445
446     return myitem->surface;
447 }
448
449 PixMask* GraphicsCache::getPortPic()
450 {
451   return getPortPic(GameMap::getInstance()->getCityset()->getId());
452 }
453
454 PixMask* GraphicsCache::getPortPic(guint32 cityset)
455 {
456     debug("getting port pic " << cityset)
457     std::list<PortCacheItem*>::iterator it;
458     PortCacheItem* myitem;
459     for (it = d_portlist.begin(); it != d_portlist.end(); it++)
460     {
461         if ((*it)->cityset == cityset)
462         {
463             myitem = (*it);
464             
465             // put the item on the last place (==last touched)
466             d_portlist.erase(it);
467             d_portlist.push_back(myitem);
468             
469             return myitem->surface;
470         }
471     }
472     // We are still here, so the graphic is not in the cache. 
473     // addPortPic calls checkPictures on its own, so we can 
474     // simply return the surface
475     myitem = addPortPic(cityset);
476
477     return myitem->surface;
478 }
479
480 PixMask* GraphicsCache::getSignpostPic()
481 {
482   return getSignpostPic(GameMap::getInstance()->getCityset()->getId());
483 }
484
485 PixMask* GraphicsCache::getSignpostPic(guint32 cityset)
486 {
487     debug("getting signpost pic " << cityset)
488     std::list<SignpostCacheItem*>::iterator it;
489     SignpostCacheItem* myitem;
490     for (it = d_signpostlist.begin(); it != d_signpostlist.end(); it++)
491     {
492         if ((*it)->cityset == cityset)
493         {
494             myitem = (*it);
495             
496             // put the item on the last place (==last touched)
497             d_signpostlist.erase(it);
498             d_signpostlist.push_back(myitem);
499             
500             return myitem->surface;
501         }
502     }
503     // We are still here, so the graphic is not in the cache. 
504     // addSignpostPic calls checkPictures on its own, so we can 
505     // simply return the surface
506     myitem = addSignpostPic(cityset);
507
508     return myitem->surface;
509 }
510
511 PixMask* GraphicsCache::getBagPic()
512 {
513   guint32 armyset = Playerlist::getActiveplayer()->getArmyset();
514   return getBagPic(armyset);
515 }
516
517 PixMask* GraphicsCache::getBagPic(guint32 armyset)
518 {
519     debug("getting bag pic " << armyset)
520     std::list<BagCacheItem*>::iterator it;
521     BagCacheItem* myitem;
522     for (it = d_baglist.begin(); it != d_baglist.end(); it++)
523     {
524         if ((*it)->armyset == armyset)
525         {
526             myitem = (*it);
527             
528             // put the item on the last place (==last touched)
529             d_baglist.erase(it);
530             d_baglist.push_back(myitem);
531             
532             return myitem->surface;
533         }
534     }
535     // We are still here, so the graphic is not in the cache. 
536     // addBagPic calls checkPictures on its own, so we can 
537     // simply return the surface
538     myitem = addBagPic(armyset);
539
540     return myitem->surface;
541 }
542
543 PixMask* GraphicsCache::getExplosionPic()
544 {
545   return getExplosionPic(GameMap::getInstance()->getTileset()->getId());
546 }
547
548 PixMask* GraphicsCache::getExplosionPic(guint32 tileset)
549 {
550     debug("getting explosion pic " << tileset)
551     std::list<ExplosionCacheItem*>::iterator it;
552     ExplosionCacheItem* myitem;
553     for (it = d_explosionlist.begin(); it != d_explosionlist.end(); it++)
554     {
555         if ((*it)->tileset == tileset)
556         {
557             myitem = (*it);
558             
559             // put the item on the last place (==last touched)
560             d_explosionlist.erase(it);
561             d_explosionlist.push_back(myitem);
562             
563             return myitem->surface;
564         }
565     }
566     // We are still here, so the graphic is not in the cache. 
567     // addExplosionPic calls checkPictures on its own, so we can 
568     // simply return the surface
569     myitem = addExplosionPic(tileset);
570
571     return myitem->surface;
572 }
573
574 PixMask* GraphicsCache::getPlantedStandardPic(const Player* p)
575 {
576     debug("getting planted standard pic " <<p->getName())
577     std::list<PlantedStandardCacheItem*>::iterator it;
578     PlantedStandardCacheItem* myitem;
579     for (it = d_plantedstandardlist.begin(); it != d_plantedstandardlist.end(); it++)
580     {
581         if ((*it)->player_id == p->getId() && (*it)->armyset == p->getArmyset())
582         {
583             myitem = (*it);
584             
585             // put the item on the last place (==last touched)
586             d_plantedstandardlist.erase(it);
587             d_plantedstandardlist.push_back(myitem);
588             
589             return myitem->surface;
590         }
591     }
592     // We are still here, so the graphic is not in the cache. 
593     // addPlantedStandardPic calls checkPictures on its own, so we can 
594     // simply return the surface
595     myitem = addPlantedStandardPic(p);
596
597     return myitem->surface;
598 }
599
600 PixMask* GraphicsCache::getArmyPic(Army *a, bool greyed)
601 {
602   return getArmyPic(a->getOwner()->getArmyset(), a->getTypeId(), 
603                     a->getOwner(), NULL, greyed);
604 }
605
606 PixMask* GraphicsCache::getArmyPic(guint32 armyset, guint32 army_id, 
607                                    const Player* p, const bool *medals,
608                                    bool greyed)
609 {
610   debug("getting army pic " <<armyset <<" " <<army <<" " <<p->getName() << 
611     " "  << greyed)
612
613     std::list<ArmyCacheItem*>::iterator it;
614     ArmyCacheItem* myitem;
615
616     // important: medals can be 0 in special cases
617     bool my_medals[3] = {0,0,0};
618     if (medals)
619         for (int i = 0; i < 3; i++)
620             my_medals[i] = medals[i];
621
622     // special situation: ruin keepers don't belong to any player
623     // we don't actually show them, but what the heck
624     if (!p)
625         p = Playerlist::getInstance()->getNeutral();
626     
627     ArmyCacheItem item = ArmyCacheItem();
628     item.armyset = armyset;
629     item.army_id = army_id;
630     item.player_id = p->getId();
631     item.medals[0] = my_medals[0];
632     item.medals[1] = my_medals[1];
633     item.medals[2] = my_medals[2];
634     item.greyed = greyed;
635     ArmyMap::iterator mit = d_armymap.find(item);
636     if (mit != d_armymap.end())
637       {
638         std::list<ArmyCacheItem*>::iterator it = (*mit).second;
639         myitem = *it;
640         d_armylist.erase(it);
641         d_armylist.push_back(myitem);
642         it = d_armylist.end();
643         it--;
644         d_armymap[*myitem] = it;
645         return myitem->surface;
646       }
647
648     // We are still here, so the graphic is not in the cache. addArmyPic calls
649     // checkPictures on its own, so we can simply return the surface
650     debug("getarmypic============= " << my_medals) 
651     myitem = addArmyPic(&item);
652
653     return myitem->surface;
654 }
655
656 PixMask* GraphicsCache::getTilePic(int tile_style_id, int fog_type_id, bool has_bag, bool has_standard, int standard_player_id, int stack_size, int stack_player_id, int army_type_id, bool has_tower, bool has_ship, Maptile::Building building_type, int building_subtype, Vector<int> building_tile, int building_player_id, guint32 tilesize, bool has_grid)
657 {
658   guint32 tileset = GameMap::getInstance()->getTileset()->getId();
659   guint32 cityset = GameMap::getInstance()->getCityset()->getId();
660   return getTilePic(tile_style_id, fog_type_id, has_bag, has_standard, standard_player_id, stack_size, stack_player_id, army_type_id, has_tower, has_ship, building_type, building_subtype, building_tile, building_player_id, tilesize, has_grid, tileset, cityset);
661 }
662
663 PixMask* GraphicsCache::getTilePic(int tile_style_id, int fog_type_id, bool has_bag, bool has_standard, int standard_player_id, int stack_size, int stack_player_id, int army_type_id, bool has_tower, bool has_ship, Maptile::Building building_type, int building_subtype, Vector<int> building_tile, int building_player_id, guint32 tilesize, bool has_grid, guint32 tileset, guint32 cityset)
664 {
665     debug("getting tile pic " << tile_style_id << " " <<
666           fog_type_id << " " << has_bag << " " << has_standard << " " <<
667           standard_player_id << " " << stack_size << " " << stack_player_id <<
668           " " << army_type_id << " " << has_tower << " " << has_ship << " " << 
669           building_type << " " << building_subtype << " " << building_tile.x 
670           << "," << building_tile.y << " " << building_player_id << " " << 
671           tilesize << " " << has_grid << " " <<tileset);
672
673     std::list<TileCacheItem*>::iterator it;
674     TileCacheItem* myitem;
675
676     TileCacheItem item = TileCacheItem();
677     item.tilesize = tilesize;
678     item.tile_style_id = tile_style_id;
679     item.has_bag = has_bag;
680     item.has_standard = has_standard;
681     item.standard_player_id = standard_player_id;
682     item.stack_size = stack_size;
683     item.stack_player_id = stack_player_id;
684     item.army_type_id = army_type_id;
685     item.has_tower = has_tower;
686     item.has_ship = has_ship;
687     item.building_type= building_type;
688     item.building_subtype= building_subtype;
689     item.building_tile = building_tile;
690     item.building_player_id = building_player_id;
691     item.has_grid = has_grid;
692     item.fog_type_id = fog_type_id;
693     item.tileset = tileset;
694     item.cityset = cityset;
695     TileMap::iterator mit = d_tilemap.find(item);
696     if (mit != d_tilemap.end())
697       {
698         std::list<TileCacheItem*>::iterator it = (*mit).second;
699         myitem = *it;
700         d_tilelist.erase(it);
701         d_tilelist.push_back(myitem);
702         it = d_tilelist.end();
703         it--;
704         d_tilemap[*myitem] = it;
705         return myitem->surface;
706       }
707
708     // We are still here, so the graphic is not in the cache. addTilePic calls
709     // checkPictures on its own, so we can simply return the surface
710     myitem = addTilePic(&item);
711
712     return myitem->surface;
713 }
714
715 PixMask* GraphicsCache::getShieldPic(guint32 shieldset, guint32 type, 
716                                      guint32 colour)
717 {
718     debug("getting shield pic " <<shieldset <<" " <<type <<" " <<colour)
719
720     std::list<ShieldCacheItem*>::iterator it;
721     ShieldCacheItem* myitem;
722
723     for (it =d_shieldlist.begin(); it != d_shieldlist.end(); it++)
724     {
725         if ((*it)->shieldset == shieldset && (*it)->type == type
726             && (*it)->colour == colour)
727         {
728             myitem = (*it);
729             
730             // put the item on the last place (==last touched)
731             d_shieldlist.erase(it);
732             d_shieldlist.push_back(myitem);
733             
734             return myitem->surface;
735         }
736     }
737
738     // We are still here, so the graphic is not in the cache. addShieldPic calls
739     // checkPictures on its own, so we can simply return the surface
740     myitem = addShieldPic(shieldset, type, colour);
741
742     return myitem->surface;
743 }
744         
745 PixMask* GraphicsCache::getShieldPic(guint32 type, Player *p)
746 {
747   guint32 shieldset = GameMap::getInstance()->getShieldset()->getId();
748   return getShieldPic(shieldset, type, p->getId());
749 }
750
751 PixMask* GraphicsCache::getTemplePic(int type)
752 {
753   guint32 cityset = GameMap::getInstance()->getCityset()->getId();
754   return getTemplePic(type, cityset);
755 }
756 PixMask* GraphicsCache::getTemplePic(int type, guint32 cityset)
757 {
758     debug("GraphicsCache::getTemplePic " <<type)
759
760     std::list<TempleCacheItem*>::iterator it;
761     TempleCacheItem* myitem;
762
763     for (it = d_templelist.begin(); it != d_templelist.end(); it++)
764     {
765         if ((*it)->type == type && (*it)->cityset == cityset)
766         {
767             myitem = (*it);
768
769             //put the item in last place (last touched)
770             d_templelist.erase(it);
771             d_templelist.push_back(myitem);
772
773             return myitem->surface;
774         }
775     }
776
777     //no item found -> create a new one
778     myitem = addTemplePic(type, cityset);
779
780     return myitem->surface;
781 }
782
783 PixMask* GraphicsCache::getRuinPic(int type)
784 {
785   guint32 cityset = GameMap::getInstance()->getCityset()->getId();
786   return getRuinPic(type, cityset);
787 }
788 PixMask* GraphicsCache::getRuinPic(int type, guint32 cityset)
789 {
790     debug("GraphicsCache::getRuinPic " <<type)
791
792     std::list<RuinCacheItem*>::iterator it;
793     RuinCacheItem* myitem;
794
795     for (it = d_ruinlist.begin(); it != d_ruinlist.end(); it++)
796     {
797         if ((*it)->type == type && (*it)->cityset == cityset)
798         {
799             myitem = (*it);
800
801             //put the item in last place (last touched)
802             d_ruinlist.erase(it);
803             d_ruinlist.push_back(myitem);
804
805             return myitem->surface;
806         }
807     }
808
809     //no item found -> create a new one
810     myitem = addRuinPic(type, cityset);
811
812     return myitem->surface;
813 }
814
815 PixMask* GraphicsCache::getDiplomacyPic(int type, Player::DiplomaticState state)
816 {
817     debug("GraphicsCache::getDiplomaticPic " <<type << ", " << state)
818
819     std::list<DiplomacyCacheItem*>::iterator it;
820     DiplomacyCacheItem* myitem;
821
822     for (it = d_diplomacylist.begin(); it != d_diplomacylist.end(); it++)
823     {
824         if ((*it)->type == type && (*it)->state == state)
825         {
826             myitem = (*it);
827
828             //put the item in last place (last touched)
829             d_diplomacylist.erase(it);
830             d_diplomacylist.push_back(myitem);
831
832             return myitem->surface;
833         }
834     }
835
836     //no item found -> create a new one
837     myitem = addDiplomacyPic(type, state);
838
839     return myitem->surface;
840 }
841
842 PixMask* GraphicsCache::getRoadPic(int type)
843 {
844   return getRoadPic(type, GameMap::getInstance()->getTileset()->getId());
845 }
846 PixMask* GraphicsCache::getRoadPic(int type, guint32 tileset)
847 {
848     debug("GraphicsCache::getRoadPic " <<type)
849
850     std::list<RoadCacheItem*>::iterator it;
851     RoadCacheItem* myitem;
852
853     for (it = d_roadlist.begin(); it != d_roadlist.end(); it++)
854     {
855         if ((*it)->type == type && (*it)->tileset == tileset)
856         {
857             myitem = (*it);
858
859             //put the item in last place (last touched)
860             d_roadlist.erase(it);
861             d_roadlist.push_back(myitem);
862
863             return myitem->surface;
864         }
865     }
866
867     //no item found -> create a new one
868     myitem = addRoadPic(type, tileset);
869
870     return myitem->surface;
871 }
872
873 PixMask* GraphicsCache::getFogPic(int type)
874 {
875   return getFogPic(type, GameMap::getInstance()->getTileset()->getId());
876 }
877
878 PixMask* GraphicsCache::getFogPic(int type, guint32 tileset)
879 {
880     debug("GraphicsCache::getFogPic " <<type)
881
882     std::list<FogCacheItem*>::iterator it;
883     FogCacheItem* myitem;
884
885     FogCacheItem item = FogCacheItem();
886     item.type = type;
887     item.tileset = tileset;
888     FogCacheMap::iterator mit = d_fogmap.find(item);
889     if (mit != d_fogmap.end())
890       {
891         std::list<FogCacheItem*>::iterator it = (*mit).second;
892         myitem = *it;
893         d_foglist.erase(it);
894         d_foglist.push_back(myitem);
895         it = d_foglist.end();
896         it--;
897         d_fogmap[*myitem] = it;
898         return myitem->surface;
899       }
900
901     //no item found -> create a new one
902     myitem = addFogPic(&item);
903
904     return myitem->surface;
905 }
906
907 PixMask* GraphicsCache::getBridgePic(int type)
908 {
909   return getBridgePic(type, GameMap::getInstance()->getTileset()->getId());
910 }
911 PixMask* GraphicsCache::getBridgePic(int type, guint32 tileset)
912 {
913     debug("GraphicsCache::getBridgePic " <<type)
914
915     std::list<BridgeCacheItem*>::iterator it;
916     BridgeCacheItem* myitem;
917
918     for (it = d_bridgelist.begin(); it != d_bridgelist.end(); it++)
919     {
920         if ((*it)->type == type && (*it)->tileset == tileset)
921         {
922             myitem = (*it);
923
924             //put the item in last place (last touched)
925             d_bridgelist.erase(it);
926             d_bridgelist.push_back(myitem);
927
928             return myitem->surface;
929         }
930     }
931
932     //no item found -> create a new one
933     myitem = addBridgePic(type, tileset);
934
935     return myitem->surface;
936 }
937
938 PixMask* GraphicsCache::getCursorPic(int type)
939 {
940     debug("GraphicsCache::getCursorPic " <<type)
941
942     std::list<CursorCacheItem*>::iterator it;
943     CursorCacheItem* myitem;
944
945     for (it = d_cursorlist.begin(); it != d_cursorlist.end(); it++)
946     {
947         if ((*it)->type == type)
948         {
949             myitem = (*it);
950
951             //put the item in last place (last touched)
952             d_cursorlist.erase(it);
953             d_cursorlist.push_back(myitem);
954
955             return myitem->surface;
956         }
957     }
958
959     //no item found -> create a new one
960     myitem = addCursorPic(type);
961
962     return myitem->surface;
963 }
964
965 PixMask* GraphicsCache::getCityPic(const City* city, guint32 cityset)
966 {
967   if (!city)
968     return NULL;
969   int type;
970   if (city->isBurnt() == true)
971     type = -1;
972   else
973     type = 0;
974   return getCityPic(type, city->getOwner(), cityset);
975 }
976
977 PixMask* GraphicsCache::getCityPic(const City* city)
978 {
979   guint32 cityset = GameMap::getInstance()->getCityset()->getId();
980   return getCityPic(city, cityset);
981 }
982
983 PixMask* GraphicsCache::getCityPic(int type, const Player* p, guint32 cityset)
984 {
985     debug("GraphicsCache::getCityPic " <<type)
986
987     std::list<CityCacheItem*>::iterator it;
988     CityCacheItem* myitem;
989
990     for (it = d_citylist.begin(); it != d_citylist.end(); it++)
991     {
992         if ((*it)->type == type && (*it)->cityset == cityset &&
993             (*it)->player_id == p->getId())
994         {
995             myitem = (*it);
996
997             //put the item in last place (last touched)
998             d_citylist.erase(it);
999             d_citylist.push_back(myitem);
1000
1001             return myitem->surface;
1002         }
1003     }
1004
1005     //no item found -> create a new one
1006     myitem = addCityPic(type, p, cityset);
1007
1008     return myitem->surface;
1009 }
1010
1011 PixMask* GraphicsCache::getTowerPic(const Player* p)
1012 {
1013   guint32 cityset = GameMap::getInstance()->getCityset()->getId();
1014   return getTowerPic(p, cityset);
1015 }
1016
1017 PixMask* GraphicsCache::getTowerPic(const Player* p, guint32 cityset)
1018 {
1019     debug("GraphicsCache::getTowerPic player " <<p->getName())
1020
1021     std::list<TowerCacheItem*>::iterator it;
1022     TowerCacheItem* myitem;
1023
1024     for (it = d_towerlist.begin(); it != d_towerlist.end(); it++)
1025     {
1026         if ((*it)->cityset == cityset && (*it)->player_id == p->getId())
1027         {
1028             myitem = (*it);
1029
1030             //put the item in last place (last touched)
1031             d_towerlist.erase(it);
1032             d_towerlist.push_back(myitem);
1033
1034             return myitem->surface;
1035         }
1036     }
1037
1038     //no item found -> create a new one
1039     myitem = addTowerPic(p, cityset);
1040
1041     return myitem->surface;
1042 }
1043
1044 PixMask* GraphicsCache::getFlagPic(guint32 stack_size, const Player *p, guint32 tileset)
1045 {
1046   if (stack_size > MAX_STACK_SIZE || p == NULL || tileset == 0)
1047     return NULL;
1048     debug("GraphicsCache::getFlagPic " <<stack_size <<", player" <<p->getId())
1049
1050     std::list<FlagCacheItem*>::iterator it;
1051     FlagCacheItem* myitem;
1052
1053     for (it = d_flaglist.begin(); it != d_flaglist.end(); it++)
1054     {
1055         myitem = *it;
1056         if (myitem->size == stack_size && myitem->player_id == p->getId() &&
1057             myitem->tileset == tileset)
1058         {
1059             // put the item in last place (last touched)
1060             d_flaglist.erase(it);
1061             d_flaglist.push_back(myitem);
1062
1063             return myitem->surface;
1064         }
1065     }
1066
1067     // no item found => create a new one
1068     myitem = addFlagPic(stack_size, p, tileset);
1069
1070     return myitem->surface;
1071 }
1072 PixMask* GraphicsCache::getFlagPic(guint32 stack_size, const Player *p)
1073 {
1074   return getFlagPic(stack_size, p, 
1075                     GameMap::getInstance()->getTileset()->getId());
1076 }
1077
1078 PixMask* GraphicsCache::getFlagPic(const Stack* s)
1079 {
1080   return getFlagPic(s, GameMap::getInstance()->getTileset()->getId());
1081 }
1082 PixMask* GraphicsCache::getFlagPic(const Stack* s, guint32 tileset)
1083 {
1084     if (!s)
1085     {
1086         std::cerr << "GraphicsCache::getFlagPic: no stack supplied! Exiting...\n";
1087         exit(-1);
1088     }
1089     
1090   return getFlagPic(s->size(), s->getOwner(), tileset);
1091 }
1092
1093 PixMask* GraphicsCache::getSelectorPic(guint32 type, guint32 frame, 
1094                                            const Player *p)
1095 {
1096   return getSelectorPic(type, frame, p, 
1097                         GameMap::getInstance()->getTileset()->getId());
1098 }
1099 PixMask* GraphicsCache::getSelectorPic(guint32 type, guint32 frame, 
1100                                            const Player *p, guint32 tileset)
1101 {
1102     debug("GraphicsCache::getSelectorPic " <<type <<", " << frame << ", player" <<s->getOwner()->getName())
1103
1104     if (!p)
1105     {
1106         std::cerr << "GraphicsCache::getSelectorPic: no player supplied! Exiting...\n";
1107         exit(-1);
1108     }
1109     
1110     std::list<SelectorCacheItem*>::iterator it;
1111     SelectorCacheItem* myitem;
1112
1113     for (it = d_selectorlist.begin(); it != d_selectorlist.end(); it++)
1114     {
1115         myitem = *it;
1116         if ((myitem->type == type) && (myitem->player_id == p->getId()) 
1117             && myitem->frame == frame && myitem->tileset == tileset)
1118         {
1119             // put the item in last place (last touched)
1120             d_selectorlist.erase(it);
1121             d_selectorlist.push_back(myitem);
1122
1123             return myitem->surface;
1124         }
1125     }
1126
1127     // no item found => create a new one
1128     myitem = addSelectorPic(type, frame, p, tileset);
1129
1130     return myitem->surface;
1131 }
1132
1133
1134 PixMask* GraphicsCache::getProdShieldPic(guint32 type, bool prod)
1135 {
1136     debug("GraphicsCache::getProdShieldPic " <<type <<", " << ", prod " <<prod)
1137
1138     std::list<ProdShieldCacheItem*>::iterator it;
1139     ProdShieldCacheItem* myitem;
1140
1141     for (it = d_prodshieldlist.begin(); it != d_prodshieldlist.end(); it++)
1142     {
1143         myitem = *it;
1144         if ((myitem->type == type) && (myitem->prod == prod))
1145         {
1146             // put the item in last place (last touched)
1147             d_prodshieldlist.erase(it);
1148             d_prodshieldlist.push_back(myitem);
1149
1150             return myitem->surface;
1151         }
1152     }
1153
1154     // no item found => create a new one
1155     myitem = addProdShieldPic(type, prod);
1156
1157     return myitem->surface;
1158 }
1159
1160
1161 PixMask* GraphicsCache::applyMask(PixMask* image, PixMask* mask, Gdk::Color colour, bool isNeutral)
1162 {
1163   int width = image->get_width();
1164   int height = image->get_height();
1165   PixMask* result = PixMask::create(image->to_pixbuf());
1166   if (mask->get_width() != width || (mask->get_height()) != height)
1167     {
1168       std::cerr <<"Warning: mask and original image do not match\n";
1169       return NULL;
1170     }
1171   if (isNeutral)
1172     return result;
1173   
1174   Glib::RefPtr<Gdk::Pixbuf> maskbuf = mask->to_pixbuf();
1175
1176   guint8 *data = maskbuf->get_pixels();
1177   guint8 *copy = (guint8*)  malloc (height * width * 4 * sizeof(guint8));
1178   memcpy(copy, data, height * width * 4 * sizeof(guint8));
1179   for (int i = 0; i < width; i++)
1180     for (int j = 0; j < height; j++)
1181       {
1182         const int base = (j * 4) + (i * height * 4);
1183
1184         if (copy[base+3] != 0)
1185           {
1186             copy[base+0] = colour.get_red_p() *copy[base+0];
1187             copy[base+1] = colour.get_green_p() * copy[base+1];
1188             copy[base+2] = colour.get_blue_p() * copy[base+2];
1189           }
1190       }
1191   Glib::RefPtr<Gdk::Pixbuf> colouredmask = 
1192     Gdk::Pixbuf::create_from_data(copy, Gdk::COLORSPACE_RGB, true, 8, 
1193                                   width, height, width * 4);
1194   result->draw_pixbuf(colouredmask, 0, 0, 0, 0, width, height);
1195   free(copy);
1196
1197   return result;
1198 }
1199
1200 PixMask* GraphicsCache::greyOut(PixMask* image)
1201 {
1202   int width = image->get_width();
1203   int height = image->get_height();
1204   PixMask* result = PixMask::create(image->to_pixbuf());
1205   
1206   guint8 *data = result->to_pixbuf()->get_pixels();
1207   guint8 *copy = (guint8*)  malloc (height * width * 4 * sizeof(guint8));
1208   memcpy(copy, data, height * width * 4 * sizeof(guint8));
1209   for (int i = 0; i < width; i++)
1210     for (int j = 0; j < height; j++)
1211       {
1212         const int base = (j * 4) + (i * height * 4);
1213
1214         if (data[base+3] != 0)
1215           {
1216             guint32 max = 0;
1217             if (copy[base+0] > max)
1218               max = copy[base+0];
1219             else if (copy[base+1] > max)
1220               max = copy[base+1];
1221             else if (copy[base+2] > max)
1222               max = copy[base+2];
1223             int x =  i % 2;
1224             int y = j % 2;
1225             if ((x == 0 && y == 0) || (x == 1 && y == 1))
1226               max = 88;
1227             copy[base+0] = max;
1228             copy[base+1] = max;
1229             copy[base+2] = max;
1230           }
1231       }
1232   Glib::RefPtr<Gdk::Pixbuf> greyed_out =  
1233     Gdk::Pixbuf::create_from_data(copy, Gdk::COLORSPACE_RGB, true, 8, 
1234                                   width, height, width * 4);
1235
1236   result->draw_pixbuf(greyed_out, 0, 0, 0, 0, width, height);
1237   free(copy);
1238
1239   return result;
1240 }
1241
1242 PixMask* GraphicsCache::applyMask(PixMask* image, PixMask* mask, const Player* p)
1243 {
1244   return applyMask(image, mask, p->getColor(),
1245                    Playerlist::getInstance()->getNeutral()->getId() == p->getId());
1246 }
1247
1248 void GraphicsCache::checkPictures()
1249 {
1250   // for security, we always take a minimum cache size of 2MB. This
1251   // includes (at 4 byte color depth and assuming 64x64 pixel size)
1252   // - 10 cities (each 64kb => 640kb)
1253   // - 20 flags (each 16kb => 320kb)
1254   // - 40 units (each 16kb => 640kb)
1255   // + a bit more. The problem is that if we have less images than needed
1256   // for a single rendering, the surfaces will become invalid before actually
1257   // used. This should not be a problem with the normal map (the surfaces are
1258   // copied and discarded), but when selecting armies from armyset, where
1259   // you can have these images assigned to buttons.
1260   guint32 maxcache = Configuration::s_cacheSize;
1261   if (maxcache < (1<<21))
1262     maxcache = (1<<21);
1263
1264   if (d_cachesize < maxcache)
1265     return;
1266
1267
1268   // Now the cache size has been exceeded. We try to guarantee the values
1269   // given above and reduce the number of images. Let us start with the
1270   // cities
1271
1272   while (d_citylist.size() > 10)
1273     eraseLastCityItem();
1274
1275   while (d_towerlist.size() > 10)
1276     eraseLastTowerItem();
1277
1278   while (d_shiplist.size() > 10)
1279     eraseLastShipItem();
1280
1281   while (d_plantedstandardlist.size() > 10)
1282     eraseLastPlantedStandardItem();
1283
1284   while (d_newlevellist.size() > 10)
1285     eraseLastNewLevelItem();
1286
1287   while (d_templelist.size() > 10)
1288     eraseLastTempleItem();
1289
1290   while (d_ruinlist.size() > 10)
1291     eraseLastRuinItem();
1292
1293   while (d_diplomacylist.size() > 10)
1294     eraseLastDiplomacyItem();
1295
1296   while (d_roadlist.size() > 18)
1297     eraseLastRoadItem();
1298
1299   while (d_foglist.size() > 16)
1300     eraseLastFogItem();
1301
1302   while (d_bridgelist.size() > 10)
1303     eraseLastBridgeItem();
1304
1305   while (d_cursorlist.size() > 10)
1306     eraseLastCursorItem();
1307
1308   // was this enough?
1309   if (d_cachesize < maxcache)
1310     return;
1311
1312   // next, kill flag pics
1313   while (d_flaglist.size() > 20)
1314     eraseLastFlagItem();
1315
1316   if (d_cachesize < maxcache)
1317     return;
1318
1319   // next, kill selector pics
1320   while (d_selectorlist.size() > 20)
1321     eraseLastSelectorItem();
1322
1323   if (d_cachesize < maxcache)
1324     return;
1325
1326   // next, kill shield pics
1327   while (d_shieldlist.size() > 20)
1328     eraseLastShieldItem();
1329
1330   if (d_cachesize < maxcache)
1331     return;
1332
1333   // next, kill production shield pics
1334   while (d_prodshieldlist.size() > 20)
1335     eraseLastProdShieldItem();
1336
1337   if (d_cachesize < maxcache)
1338     return;
1339
1340   // next, kill port pics
1341   while (d_portlist.size() > 1)
1342     eraseLastPortItem();
1343
1344   if (d_cachesize < maxcache)
1345     return;
1346
1347   // next, kill signpost pics
1348   while (d_signpostlist.size() > 1)
1349     eraseLastSignpostItem();
1350
1351   if (d_cachesize < maxcache)
1352     return;
1353
1354   // next, kill bag pics
1355   while (d_baglist.size() > 1)
1356     eraseLastBagItem();
1357
1358   if (d_cachesize < maxcache)
1359     return;
1360
1361   // next, kill explosion pics
1362   while (d_explosionlist.size() > 1)
1363     eraseLastExplosionItem();
1364
1365   if (d_cachesize < maxcache)
1366     return;
1367
1368   // next, kill movement bonus pics
1369   while (d_movebonuslist.size() > 20)
1370     eraseLastMoveBonusItem();
1371
1372   if (d_cachesize < maxcache)
1373     return;
1374
1375   // still not enough? Erase tile images
1376   while (d_tilelist.size() > 200)
1377     eraseLastTileItem();
1378
1379   // still not enough? Erase army images
1380   while (d_armylist.size() > 40)
1381     eraseLastArmyItem();
1382
1383 }
1384
1385 void GraphicsCache::drawTilePic(PixMask *surface, int fog_type_id, bool has_bag, bool has_standard, int standard_player_id, int stack_size, int stack_player_id, int army_type_id, bool has_tower, bool has_ship, Maptile::Building building_type, int building_subtype, Vector<int> building_tile, int building_player_id, guint32 ts, bool has_grid, guint32 tileset, guint32 cityset)
1386 {
1387   const Player *player;
1388   Glib::RefPtr<Gdk::Pixmap> pixmap = surface->get_pixmap();
1389
1390   switch (building_type)
1391     {
1392     case Maptile::CITY:
1393         {
1394           player = Playerlist::getInstance()->getPlayer(building_player_id);
1395           getCityPic(building_subtype, player, cityset)->blit(building_tile, ts, pixmap);
1396         }
1397       break;
1398     case Maptile::RUIN:
1399       getRuinPic(building_subtype, cityset)->blit(building_tile, ts, pixmap); break;
1400     case Maptile::TEMPLE:
1401       getTemplePic(building_subtype, cityset)->blit(building_tile, ts, pixmap); break;
1402     case Maptile::SIGNPOST:
1403       getSignpostPic(cityset)->blit(building_tile, ts, pixmap); break;
1404     case Maptile::ROAD:
1405       getRoadPic(building_subtype)->blit(building_tile, ts, pixmap); break;
1406     case Maptile::PORT:
1407       getPortPic(cityset)->blit(building_tile, ts, pixmap); break;
1408     case Maptile::BRIDGE:
1409       getBridgePic(building_subtype)->blit(building_tile, ts, pixmap); break;
1410       break;
1411     case Maptile::NONE: default:
1412       break;
1413     }
1414
1415   if (has_standard)
1416     {
1417       player = Playerlist::getInstance()->getPlayer(standard_player_id) ;
1418       getPlantedStandardPic(player)->blit(pixmap);
1419     }
1420
1421   if (has_bag)
1422     {
1423       PixMask *pic = getBagPic();
1424       Vector<int>bagsize = Vector<int>(pic->get_width(), pic->get_height());
1425       pic->blit(pixmap, Vector<int>(ts,ts)-bagsize);
1426     }
1427
1428   if (stack_player_id > -1)
1429     {
1430       player = Playerlist::getInstance()->getPlayer(stack_player_id);
1431       if (has_tower)
1432         getTowerPic(player)->blit(pixmap);
1433       else
1434         {
1435           if (stack_size > -1)
1436             getFlagPic(stack_size, player)->blit(pixmap);
1437           if (has_ship)
1438             getShipPic(player)->blit(pixmap);
1439           else
1440             getArmyPic(player->getArmyset(), army_type_id, player, NULL)->blit(pixmap);
1441         }
1442     }
1443   if (has_grid)
1444     {
1445       Glib::RefPtr<Gdk::GC> context = surface->get_gc();
1446       Gdk::Color line_color = Gdk::Color();
1447       line_color.set_rgb_p(0,0,0);
1448       context->set_rgb_fg_color(line_color);
1449       pixmap->draw_rectangle(context, false, 0, 0, ts, ts);
1450     }
1451
1452   if (fog_type_id)
1453     {
1454       Tileset *t= 
1455         Tilesetlist::getInstance()->getTileset(tileset);
1456       t->getFogImage(fog_type_id - 1)->blit(pixmap);
1457     }
1458 }
1459
1460 TileCacheItem* GraphicsCache::addTilePic(TileCacheItem *item)
1461 {
1462     
1463   debug("ADD tile pic " << " " << item->tile_style_id << " " <<
1464         item->fog_type_id << " " << item->has_bag << " " << 
1465         item->has_standard << " " << item->standard_player_id << " " << 
1466         item->stack_size << " " << item->stack_player_id <<
1467         " " << item->army_type_id << " " << item->has_tower << " " << 
1468         item->has_ship << " " << item->building_type << " " << 
1469         item->building_subtype << " " << item->building_tile.x << 
1470         "," << item->building_tile.y << " " << item->building_player_id << 
1471         " " << item->tilesize << " " << item->has_grid << " " << item->tileset
1472         " " << item->cityset);
1473
1474   TileCacheItem* myitem = new TileCacheItem();
1475   *myitem = *item;
1476
1477   //short circuit the drawing sequence if the tile is completely obscured
1478   Tileset *t = Tilesetlist::getInstance()->getTileset(item->tileset);
1479   if (myitem->fog_type_id == FogMap::ALL)
1480     myitem->surface = t->getFogImage(myitem->fog_type_id - 1)->copy();
1481   else
1482     {
1483       myitem->surface = 
1484         t->getTileStyle(myitem->tile_style_id)->getImage()->copy();
1485     
1486       drawTilePic(myitem->surface, myitem->fog_type_id, myitem->has_bag, 
1487                   myitem->has_standard, myitem->standard_player_id, 
1488                   myitem->stack_size, myitem->stack_player_id, 
1489                   myitem->army_type_id, myitem->has_tower, myitem->has_ship, 
1490                   myitem->building_type, myitem->building_subtype, 
1491                   myitem->building_tile, myitem->building_player_id, 
1492                   myitem->tilesize, myitem->has_grid, myitem->tileset,
1493                   myitem->cityset);
1494     }
1495
1496   //now the final preparation steps:
1497   //a) add the size
1498   int size = myitem->surface->get_width() * myitem->surface->get_height();
1499   d_cachesize += myitem->surface->get_depth()/8 * size;
1500
1501   //b) add the entry to the list
1502   d_tilelist.push_back(myitem);
1503   std::list<TileCacheItem*>::iterator it = d_tilelist.end();
1504   it--;
1505   d_tilemap[*myitem] = it;
1506
1507   //c) check if the cache size is too large
1508   checkPictures();
1509
1510   //we are finished, so return the pic
1511   return myitem;
1512 }
1513
1514 ArmyCacheItem* GraphicsCache::addArmyPic(ArmyCacheItem *item)
1515 {
1516   debug("ADD army pic: " <<item->armyset <<"," <<item->army_id)
1517
1518   ArmyCacheItem* myitem = new ArmyCacheItem();
1519   *myitem = *item;
1520
1521   const ArmyProto * basearmy = 
1522     Armysetlist::getInstance()->getArmy(myitem->armyset, myitem->army_id);
1523
1524   // copy the pixmap including player colors
1525   Player *p = Playerlist::getInstance()->getPlayer(myitem->player_id);
1526   Shield::Colour c = Shield::Colour(p->getId());
1527   PixMask *coloured = applyMask(basearmy->getImage(c), basearmy->getMask(c), p);
1528   if (myitem->greyed)
1529     {
1530       PixMask *greyed_out = greyOut(coloured);
1531       myitem->surface = greyed_out;
1532       delete coloured;
1533     }
1534   else
1535       myitem->surface = coloured;
1536
1537   if (myitem->medals != NULL)
1538     {
1539       debug("medalsbonus============= " << medalsbonus); 
1540       for(int i=0;i<3;i++)
1541         { 
1542           if (myitem->medals[i])
1543             d_medalpic[0][i]->blit(myitem->surface->get_pixmap());
1544         }
1545     }
1546
1547   //now the final preparation steps:
1548   //a) add the size
1549   int size = myitem->surface->get_width() * myitem->surface->get_height();
1550   d_cachesize += myitem->surface->get_depth()/8 * size;
1551
1552   //b) add the entry to the list
1553   d_armylist.push_back(myitem);
1554   std::list<ArmyCacheItem*>::iterator it = d_armylist.end();
1555   it--;
1556   d_armymap[*myitem] = it;
1557
1558   //c) check if the cache size is too large
1559   checkPictures();
1560
1561   //we are finished, so return the pic
1562   return myitem;
1563 }
1564
1565 ShieldCacheItem* GraphicsCache::addShieldPic(guint32 shieldset, guint32 type, 
1566                                              guint32 colour)
1567 {
1568   debug("ADD shield pic: " <<shieldset <<"," <<type <<"," <<colour)
1569
1570   ShieldCacheItem* myitem = new ShieldCacheItem();
1571   myitem->shieldset = shieldset;
1572   myitem->type = type;
1573   myitem->colour = colour;
1574
1575   ShieldStyle *sh;
1576   sh = Shieldsetlist::getInstance()->getShield(shieldset, type, colour);
1577
1578   // copy the pixmap including player colors
1579   //lookup the shieldstyle
1580   myitem->surface = applyMask(sh->getImage(), sh->getMask(), 
1581                               Playerlist::getInstance()->getPlayer(colour));
1582
1583   //now the final preparation steps:
1584   //a) add the size
1585   int size = myitem->surface->get_width() * myitem->surface->get_height();
1586   d_cachesize += myitem->surface->get_depth()/8 * size;
1587
1588   //b) add the entry to the list
1589   d_shieldlist.push_back(myitem);
1590
1591   //c) check if the cache size is too large
1592   checkPictures();
1593
1594   //we are finished, so return the pic
1595   return myitem;
1596 }
1597
1598
1599 ShipCacheItem* GraphicsCache::addShipPic(const Player* p)
1600 {
1601   debug("ADD ship pic: " <<p->getName())
1602
1603   ShipCacheItem* myitem = new ShipCacheItem();
1604   myitem->player_id = p->getId();
1605   myitem->armyset = p->getArmyset();
1606
1607   Armysetlist *al = Armysetlist::getInstance();
1608   PixMask*ship = al->getShipPic(p->getArmyset());
1609   PixMask*shipmask = al->getShipMask(p->getArmyset());
1610   // copy the pixmap including player colors
1611   myitem->surface = applyMask(ship, shipmask, p);
1612
1613   //now the final preparation steps:
1614   //a) add the size
1615   int size = myitem->surface->get_width() * myitem->surface->get_height();
1616   d_cachesize += myitem->surface->get_depth()/8 * size;
1617
1618   //b) add the entry to the list
1619   d_shiplist.push_back(myitem);
1620
1621   //c) check if the cache size is too large
1622   checkPictures();
1623
1624   //we are finished, so return the pic
1625   return myitem;
1626 }
1627
1628 NewLevelCacheItem* GraphicsCache::addNewLevelPic(const Player* p, guint32 gender)
1629 {
1630   debug("ADD new level pic: " <<p->getName())
1631
1632   NewLevelCacheItem* myitem = new NewLevelCacheItem();
1633   myitem->player_id = p->getId();
1634   myitem->gender = gender;
1635
1636   // copy the pixmap including player colors
1637   if (gender == Hero::FEMALE)
1638     myitem->surface = applyMask(d_newlevel_female, d_newlevelmask_female, p);
1639   else
1640     myitem->surface = applyMask(d_newlevel_male, d_newlevelmask_male, p);
1641
1642   //now the final preparation steps:
1643   //a) add the size
1644   int size = myitem->surface->get_width() * myitem->surface->get_height();
1645   d_cachesize += myitem->surface->get_depth()/8 * size;
1646
1647   //b) add the entry to the list
1648   d_newlevellist.push_back(myitem);
1649
1650   //c) check if the cache size is too large
1651   checkPictures();
1652
1653   //we are finished, so return the pic
1654   return myitem;
1655 }
1656
1657 PortCacheItem* GraphicsCache::addPortPic(guint32 cityset)
1658 {
1659   debug("ADD port pic: " << cityset);
1660
1661   PortCacheItem* myitem = new PortCacheItem();
1662   myitem->cityset = cityset;
1663
1664   Citysetlist *csl = Citysetlist::getInstance();
1665   Cityset *cs = csl->getCityset(cityset);
1666
1667   // copy the pixmap
1668   myitem->surface = cs->getPortImage()->copy();
1669
1670   //now the final preparation steps:
1671   //a) add the size
1672   int size = myitem->surface->get_width() * myitem->surface->get_height();
1673   d_cachesize += myitem->surface->get_depth()/8 * size;
1674
1675   //b) add the entry to the list
1676   d_portlist.push_back(myitem);
1677
1678   //c) check if the cache size is too large
1679   checkPictures();
1680
1681   //we are finished, so return the pic
1682   return myitem;
1683 }
1684
1685 ExplosionCacheItem* GraphicsCache::addExplosionPic(guint32 tileset)
1686 {
1687   debug("ADD explosion pic: " << tileset);
1688
1689   ExplosionCacheItem* myitem = new ExplosionCacheItem();
1690   myitem->tileset = tileset;
1691
1692   // copy the pixmap
1693   myitem->surface = 
1694     Tilesetlist::getInstance()->getTileset(tileset)->getExplosionImage()->copy();
1695
1696   //now the final preparation steps:
1697   //a) add the size
1698   int size = myitem->surface->get_width() * myitem->surface->get_height();
1699   d_cachesize += myitem->surface->get_depth()/8 * size;
1700
1701   //b) add the entry to the list
1702   d_explosionlist.push_back(myitem);
1703
1704   //c) check if the cache size is too large
1705   checkPictures();
1706
1707   //we are finished, so return the pic
1708   return myitem;
1709 }
1710
1711 BagCacheItem* GraphicsCache::addBagPic(guint32 armyset)
1712 {
1713   debug("ADD bad pic: " << armyset);
1714
1715   BagCacheItem* myitem = new BagCacheItem();
1716   myitem->armyset = armyset;
1717
1718   // copy the pixmap
1719   myitem->surface = Armysetlist::getInstance()->getBagPic(armyset)->copy();
1720
1721   //now the final preparation steps:
1722   //a) add the size
1723   int size = myitem->surface->get_width() * myitem->surface->get_height();
1724   d_cachesize += myitem->surface->get_depth()/8 * size;
1725
1726   //b) add the entry to the list
1727   d_baglist.push_back(myitem);
1728
1729   //c) check if the cache size is too large
1730   checkPictures();
1731
1732   //we are finished, so return the pic
1733   return myitem;
1734 }
1735
1736 SignpostCacheItem* GraphicsCache::addSignpostPic(guint32 cityset)
1737 {
1738   debug("ADD signpost pic: " << cityset);
1739
1740   SignpostCacheItem* myitem = new SignpostCacheItem();
1741   myitem->cityset = cityset;
1742
1743   Citysetlist *csl = Citysetlist::getInstance();
1744   Cityset *cs = csl->getCityset(cityset);
1745
1746   // copy the pixmap
1747   myitem->surface = cs->getSignpostImage()->copy();
1748
1749   //now the final preparation steps:
1750   //a) add the size
1751   int size = myitem->surface->get_width() * myitem->surface->get_height();
1752   d_cachesize += myitem->surface->get_depth()/8 * size;
1753
1754   //b) add the entry to the list
1755   d_signpostlist.push_back(myitem);
1756
1757   //c) check if the cache size is too large
1758   checkPictures();
1759
1760   //we are finished, so return the pic
1761   return myitem;
1762 }
1763
1764 PlantedStandardCacheItem* GraphicsCache::addPlantedStandardPic(const Player* p)
1765 {
1766   debug("ADD planted standard pic: " <<p->getName())
1767
1768     PlantedStandardCacheItem* myitem = new PlantedStandardCacheItem();
1769   myitem->player_id = p->getId();
1770   myitem->armyset = p->getArmyset();
1771
1772   Armysetlist *al = Armysetlist::getInstance();
1773   PixMask*standard = al->getStandardPic(p->getArmyset());
1774   PixMask*standard_mask = al->getStandardMask(p->getArmyset());
1775
1776   // copy the pixmap including player colors
1777   myitem->surface = applyMask(standard, standard_mask, p);
1778
1779   //now the final preparation steps:
1780   //a) add the size
1781   int size = myitem->surface->get_width() * myitem->surface->get_height();
1782   d_cachesize += myitem->surface->get_depth()/8 * size;
1783
1784   //b) add the entry to the list
1785   d_plantedstandardlist.push_back(myitem);
1786
1787   //c) check if the cache size is too large
1788   checkPictures();
1789
1790   //we are finished, so return the pic
1791   return myitem;
1792 }
1793
1794
1795 TempleCacheItem* GraphicsCache::addTemplePic(int type, guint32 cityset)
1796 {
1797   Cityset *cs = Citysetlist::getInstance()->getCityset(cityset);
1798   PixMask* mysurf = cs->getTempleImage(type)->copy();
1799
1800   //now create the cache item and add the size
1801   TempleCacheItem* myitem = new TempleCacheItem();
1802   myitem->type = type;
1803   myitem->cityset = cityset;
1804   myitem->surface = mysurf;
1805
1806   d_templelist.push_back(myitem);
1807
1808   //add the size
1809   int size = mysurf->get_width() * mysurf->get_height();
1810   d_cachesize += size * mysurf->get_depth()/8;
1811
1812   //and check the size of the cache
1813   checkPictures();
1814
1815   return myitem;
1816 }
1817
1818 RuinCacheItem* GraphicsCache::addRuinPic(int type, guint32 cityset)
1819 {
1820   Cityset *cs = Citysetlist::getInstance()->getCityset(cityset);
1821   PixMask* mysurf = cs->getRuinImage(type)->copy();
1822
1823   //now create the cache item and add the size
1824   RuinCacheItem* myitem = new RuinCacheItem();
1825   myitem->type = type;
1826   myitem->cityset = cityset;
1827   myitem->surface = mysurf;
1828   myitem->cityset = cityset;
1829
1830   d_ruinlist.push_back(myitem);
1831
1832   //add the size
1833   int size = mysurf->get_width() * mysurf->get_height();
1834   d_cachesize += size * mysurf->get_depth()/8;
1835
1836   //and check the size of the cache
1837   checkPictures();
1838
1839   return myitem;
1840 }
1841
1842 DiplomacyCacheItem* GraphicsCache::addDiplomacyPic(int type, Player::DiplomaticState state)
1843 {
1844   PixMask* mysurf = 
1845     d_diplomacypic[type][state - Player::AT_PEACE];
1846
1847   //now create the cache item and add the size
1848   DiplomacyCacheItem* myitem = new DiplomacyCacheItem();
1849   myitem->type = type;
1850   myitem->state = state;
1851   myitem->surface = mysurf;
1852
1853   d_diplomacylist.push_back(myitem);
1854
1855   //add the size
1856   int size = mysurf->get_width() * mysurf->get_height();
1857   d_cachesize += size * mysurf->get_depth()/8;
1858
1859   //and check the size of the cache
1860   checkPictures();
1861
1862   return myitem;
1863 }
1864
1865 RoadCacheItem* GraphicsCache::addRoadPic(int type, guint32 tileset)
1866 {
1867   Tileset *ts = Tilesetlist::getInstance()->getTileset(tileset);
1868   PixMask* mysurf = ts->getRoadImage(type)->copy();
1869
1870   //now create the cache item and add the size
1871   RoadCacheItem* myitem = new RoadCacheItem();
1872   myitem->type = type;
1873   myitem->tileset = tileset;
1874   myitem->surface = mysurf;
1875
1876   d_roadlist.push_back(myitem);
1877
1878   //add the size
1879   int size = mysurf->get_width() * mysurf->get_height();
1880   d_cachesize += size * mysurf->get_depth()/8;
1881
1882   //and check the size of the cache
1883   checkPictures();
1884
1885   return myitem;
1886 }
1887
1888 FogCacheItem* GraphicsCache::addFogPic(FogCacheItem *item)
1889 {
1890   Tileset *ts = Tilesetlist::getInstance()->getTileset(item->tileset);
1891   PixMask* mysurf = ts->getFogImage(item->type - 1)->copy();
1892
1893   //now create the cache item and add the size
1894   FogCacheItem* myitem = new FogCacheItem();
1895   *myitem = *item;
1896   myitem->surface = mysurf;
1897
1898   d_foglist.push_back(myitem);
1899   std::list<FogCacheItem*>::iterator it = d_foglist.end();
1900   it--;
1901   d_fogmap[*myitem] = it;
1902
1903   //add the size
1904   int size = mysurf->get_width() * mysurf->get_height();
1905   d_cachesize += size * mysurf->get_depth()/8;
1906
1907   //and check the size of the cache
1908   checkPictures();
1909
1910   return myitem;
1911 }
1912
1913 BridgeCacheItem* GraphicsCache::addBridgePic(int type, guint32 tileset)
1914 {
1915   Tileset *ts = Tilesetlist::getInstance()->getTileset(tileset);
1916   PixMask* mysurf = ts->getBridgeImage(type)->copy();
1917
1918   //now create the cache item and add the size
1919   BridgeCacheItem* myitem = new BridgeCacheItem();
1920   myitem->type = type;
1921   myitem->tileset = tileset;
1922   myitem->surface = mysurf;
1923
1924   d_bridgelist.push_back(myitem);
1925
1926   //add the size
1927   int size = mysurf->get_width() * mysurf->get_height();
1928   d_cachesize += size * mysurf->get_depth()/8;
1929
1930   //and check the size of the cache
1931   checkPictures();
1932
1933   return myitem;
1934 }
1935
1936 CursorCacheItem* GraphicsCache::addCursorPic(int type)
1937 {
1938   PixMask* mysurf = d_cursorpic[type];
1939
1940   //now create the cache item and add the size
1941   CursorCacheItem* myitem = new CursorCacheItem();
1942   myitem->type = type;
1943   myitem->surface = mysurf;
1944
1945   d_cursorlist.push_back(myitem);
1946
1947   //add the size
1948   int size = mysurf->get_width() * mysurf->get_height();
1949   d_cachesize += size * mysurf->get_depth()/8;
1950
1951   //and check the size of the cache
1952   checkPictures();
1953
1954   return myitem;
1955 }
1956
1957 CityCacheItem* GraphicsCache::addCityPic(int type, const Player* p, guint32 cityset)
1958 {
1959   //now create the cache item and add the size
1960   CityCacheItem* myitem = new CityCacheItem();
1961   myitem->cityset = cityset;
1962   myitem->player_id = p->getId();
1963   myitem->type = type;
1964   Cityset *cs = Citysetlist::getInstance()->getCityset(cityset);
1965   if (type == -1)
1966     myitem->surface = cs->getRazedCityImage(p->getId())->copy();
1967   else
1968     myitem->surface = cs->getCityImage(p->getId())->copy();
1969
1970   d_citylist.push_back(myitem);
1971
1972   //add the size
1973   int size = myitem->surface->get_width() * myitem->surface->get_height();
1974   d_cachesize += size * myitem->surface->get_depth()/8;
1975
1976   //and check the size of the cache
1977   checkPictures();
1978
1979   return myitem;
1980 }
1981
1982 TowerCacheItem* GraphicsCache::addTowerPic(const Player* p, guint32 cityset)
1983 {
1984   //now create the cache item and add the size
1985   TowerCacheItem* myitem = new TowerCacheItem();
1986   myitem->player_id = p->getId();
1987   myitem->cityset = cityset;
1988   Cityset *cs = Citysetlist::getInstance()->getCityset(cityset);
1989   myitem->surface = cs->getTowerImage(p->getId());
1990
1991   d_towerlist.push_back(myitem);
1992
1993   //add the size
1994   int size = myitem->surface->get_width() * myitem->surface->get_height();
1995   d_cachesize += size * myitem->surface->get_depth()/8;
1996
1997   //and check the size of the cache
1998   checkPictures();
1999
2000   return myitem;
2001 }
2002
2003 FlagCacheItem* GraphicsCache::addFlagPic(int size, const Player *p, guint32 tileset)
2004 {
2005   Tileset *ts = Tilesetlist::getInstance()->getTileset(tileset);
2006   debug("GraphicsCache::addFlagPic, player="<<p->getId()<<", size="<<size)
2007
2008   // size of the stack starts at 1, but we need the index, which starts at 0
2009
2010   PixMask* mysurf = applyMask (ts->getFlagImage(size-1), 
2011                                ts->getFlagMask(size-1), p);
2012
2013   //now create the cache item and add the size
2014   FlagCacheItem* myitem = new FlagCacheItem();
2015   myitem->player_id = p->getId();
2016   myitem->size = size;
2017   myitem->tileset = tileset;
2018   myitem->surface = mysurf;
2019
2020   d_flaglist.push_back(myitem);
2021
2022   //add the size
2023   int picsize = mysurf->get_width() * mysurf->get_height();
2024   d_cachesize += picsize * mysurf->get_depth()/8;
2025
2026   //and check the size of the cache
2027   checkPictures();
2028
2029   return myitem;
2030 }
2031
2032 SelectorCacheItem* GraphicsCache::addSelectorPic(guint32 type, guint32 frame, const Player* p, guint32 tileset)
2033 {
2034   Tileset *ts = Tilesetlist::getInstance()->getTileset(tileset);
2035   debug("GraphicsCache::addSelectorPic, player="<<p->getName()<<", type="<<type<< ", " << frame)
2036
2037     // frame is the frame of animation we're looking for.  starts at 0.
2038     // type is 0 for big, 1 for small
2039
2040   PixMask* mysurf;
2041   if (type == 0)
2042     mysurf = applyMask(ts->getSelectorImage(frame), ts->getSelectorMask(frame), p);
2043   else
2044     mysurf = applyMask(ts->getSmallSelectorImage(frame), 
2045                        ts->getSmallSelectorMask(frame), p);
2046
2047   //now create the cache item and add the size
2048   SelectorCacheItem* myitem = new SelectorCacheItem();
2049   myitem->player_id = p->getId();
2050   myitem->type = type;
2051   myitem->tileset = tileset;
2052   myitem->frame = frame;
2053   myitem->surface = mysurf;
2054
2055   d_selectorlist.push_back(myitem);
2056
2057   //add the size
2058   int picsize = mysurf->get_width() * mysurf->get_height();
2059   d_cachesize += picsize * mysurf->get_depth()/8;
2060
2061   //and check the size of the cache
2062   checkPictures();
2063
2064   return myitem;
2065 }
2066
2067 ProdShieldCacheItem* GraphicsCache::addProdShieldPic(guint32 type, bool prod)
2068 {
2069   debug("GraphicsCache::addProdShieldPic, prod="<<prod<<", type="<<type)
2070
2071     // type is 0 for home, 1 for away, 2 for destination, 3 for source,
2072     // 4 for invalid
2073
2074     PixMask* mysurf = NULL;
2075   switch (type)
2076     {
2077     case 0: //home city
2078       if (prod) //production
2079         mysurf = d_prodshieldpic[1]->copy();
2080       else //no production
2081         mysurf = d_prodshieldpic[0]->copy();
2082       break;
2083     case 1: //away city
2084       if (prod) //production
2085         mysurf = d_prodshieldpic[3]->copy();
2086       else //no production
2087         mysurf = d_prodshieldpic[2]->copy();
2088       break;
2089     case 2: //destination city
2090       if (prod) //production
2091         mysurf = d_prodshieldpic[5]->copy();
2092       else //no production
2093         mysurf = d_prodshieldpic[4]->copy();
2094       break;
2095     case 3: //source city
2096       mysurf = d_prodshieldpic[6]->copy();
2097       break;
2098     case 4: //invalid
2099       mysurf = d_prodshieldpic[7]->copy();
2100       break;
2101     }
2102
2103   //now create the cache item and add the size
2104   ProdShieldCacheItem* myitem = new ProdShieldCacheItem();
2105   myitem->prod = prod;
2106   myitem->type = type;
2107   myitem->surface = mysurf;
2108
2109   d_prodshieldlist.push_back(myitem);
2110
2111   //add the size
2112   int picsize = mysurf->get_width() * mysurf->get_height();
2113   d_cachesize += picsize * mysurf->get_depth()/8;
2114
2115   //and check the size of the cache
2116   checkPictures();
2117
2118   return myitem;
2119 }
2120
2121 MoveBonusCacheItem* GraphicsCache::addMoveBonusPic(guint32 type)
2122 {
2123   debug("GraphicsCache::addMoveBonusPic, type="<<type)
2124
2125     //type is 0=empty, 1=trees, 2=foothills, 3=hills+trees, 4=fly, 5=boat
2126
2127     PixMask* mysurf;
2128   mysurf = d_movebonuspic[type]->copy();
2129
2130   //now create the cache item and add the size
2131   MoveBonusCacheItem* myitem = new MoveBonusCacheItem();
2132   myitem->type = type;
2133   myitem->surface = mysurf;
2134
2135   d_movebonuslist.push_back(myitem);
2136
2137   //add the size
2138   int picsize = mysurf->get_width() * mysurf->get_height();
2139   d_cachesize += picsize * mysurf->get_depth()/8;
2140
2141   //and check the size of the cache
2142   checkPictures();
2143
2144   return myitem;
2145 }
2146
2147
2148 void GraphicsCache::clear()
2149 {
2150   while (!d_armylist.empty())
2151     eraseLastArmyItem();
2152
2153   while (!d_tilelist.empty())
2154     eraseLastTileItem();
2155
2156   while (!d_templelist.empty())
2157     eraseLastTempleItem();
2158
2159   while (!d_ruinlist.empty())
2160     eraseLastRuinItem();
2161
2162   while (!d_diplomacylist.empty())
2163     eraseLastDiplomacyItem();
2164
2165   while (!d_roadlist.empty())
2166     eraseLastRoadItem();
2167
2168   while (!d_foglist.empty())
2169     eraseLastFogItem();
2170
2171   while (!d_bridgelist.empty())
2172     eraseLastBridgeItem();
2173
2174   while (!d_cursorlist.empty())
2175     eraseLastCursorItem();
2176
2177   while (!d_citylist.empty())
2178     eraseLastCityItem();
2179
2180   while (!d_towerlist.empty())
2181     eraseLastTowerItem();
2182
2183   while (!d_shiplist.empty())
2184     eraseLastShipItem();
2185
2186   while (!d_plantedstandardlist.empty())
2187     eraseLastPlantedStandardItem();
2188
2189   while (!d_portlist.empty())
2190     eraseLastPortItem();
2191
2192   while (!d_signpostlist.empty())
2193     eraseLastSignpostItem();
2194
2195   while (!d_baglist.empty())
2196     eraseLastBagItem();
2197
2198   while (!d_explosionlist.empty())
2199     eraseLastExplosionItem();
2200
2201   while (!d_flaglist.empty())
2202     eraseLastFlagItem();
2203
2204   while (!d_selectorlist.empty())
2205     eraseLastSelectorItem();
2206
2207   while (!d_shieldlist.empty())
2208     eraseLastShieldItem();
2209
2210   while (!d_prodshieldlist.empty())
2211     eraseLastProdShieldItem();
2212
2213   while (!d_movebonuslist.empty())
2214     eraseLastMoveBonusItem();
2215 }
2216
2217 void GraphicsCache::eraseLastArmyItem()
2218 {
2219   if (d_armylist.empty())
2220     return;
2221
2222   //As the name suggests, this function erases the last item in the list.
2223   //Whenever an item is requested, it moves to the first position, so the
2224   //last item is the oldest and therefore propably most useless in the list.
2225   ArmyCacheItem* myitem = *(d_armylist.begin());
2226   ArmyMap::iterator it = d_armymap.find(*myitem);
2227   if (it != d_armymap.end())
2228     d_armymap.erase(it);
2229   d_armylist.erase(d_armylist.begin());
2230
2231   //don't forget to subtract the size from the size entry
2232   int size = myitem->surface->get_width() * myitem->surface->get_height();
2233   d_cachesize -= myitem->surface->get_depth()/8 * size;
2234
2235   delete myitem->surface;
2236   delete myitem;
2237 }
2238
2239 void GraphicsCache::eraseLastTileItem()
2240 {
2241   if (d_tilelist.empty())
2242     return;
2243
2244   //As the name suggests, this function erases the last item in the list.
2245   //Whenever an item is requested, it moves to the first position, so the
2246   //last item is the oldest and therefore propably most useless in the list.
2247   TileCacheItem* myitem = *(d_tilelist.begin());
2248   TileMap::iterator it = d_tilemap.find(*myitem);
2249   if (it != d_tilemap.end()) //fixme, find out why this check is necessary.
2250     d_tilemap.erase(it);
2251   d_tilelist.erase(d_tilelist.begin());
2252
2253   //don't forget to subtract the size from the size entry
2254   int size = myitem->surface->get_width() * myitem->surface->get_height();
2255   d_cachesize -= myitem->surface->get_depth()/8 * size;
2256
2257   delete myitem->surface;
2258   delete myitem;
2259 }
2260
2261 void GraphicsCache::eraseLastTempleItem()
2262 {
2263   if (d_templelist.empty())
2264     return;
2265
2266   TempleCacheItem* myitem = *(d_templelist.begin());
2267   d_templelist.erase(d_templelist.begin());
2268
2269   int size = myitem->surface->get_width() * myitem->surface->get_height();
2270   d_cachesize -= myitem->surface->get_depth()/8 * size;
2271
2272   delete myitem->surface;
2273   delete myitem;
2274 }
2275
2276 void GraphicsCache::eraseLastRuinItem()
2277 {
2278   if (d_ruinlist.empty())
2279     return;
2280
2281   RuinCacheItem* myitem = *(d_ruinlist.begin());
2282   d_ruinlist.erase(d_ruinlist.begin());
2283
2284   int size = myitem->surface->get_width() * myitem->surface->get_height();
2285   d_cachesize -= myitem->surface->get_depth()/8 * size;
2286
2287   delete myitem->surface;
2288   delete myitem;
2289 }
2290
2291 void GraphicsCache::eraseLastDiplomacyItem()
2292 {
2293   if (d_diplomacylist.empty())
2294     return;
2295
2296   DiplomacyCacheItem* myitem = *(d_diplomacylist.begin());
2297   d_diplomacylist.erase(d_diplomacylist.begin());
2298
2299   int size = myitem->surface->get_width() * myitem->surface->get_height();
2300   d_cachesize -= myitem->surface->get_depth()/8 * size;
2301
2302   delete myitem->surface;
2303   delete myitem;
2304 }
2305
2306 void GraphicsCache::eraseLastRoadItem()
2307 {
2308   if (d_roadlist.empty())
2309     return;
2310
2311   RoadCacheItem* myitem = *(d_roadlist.begin());
2312   d_roadlist.erase(d_roadlist.begin());
2313
2314   int size = myitem->surface->get_width() * myitem->surface->get_height();
2315   d_cachesize -= myitem->surface->get_depth()/8 * size;
2316
2317   delete myitem->surface;
2318   delete myitem;
2319 }
2320
2321 void GraphicsCache::eraseLastFogItem()
2322 {
2323   if (d_foglist.empty())
2324     return;
2325
2326   FogCacheItem* myitem = *(d_foglist.begin());
2327   FogCacheMap::iterator it = d_fogmap.find(*myitem);
2328   if (it != d_fogmap.end())
2329     d_fogmap.erase(it);
2330   d_foglist.erase(d_foglist.begin());
2331
2332   int size = myitem->surface->get_width() * myitem->surface->get_height();
2333   d_cachesize -= myitem->surface->get_depth()/8 * size;
2334
2335   delete myitem->surface;
2336   delete myitem;
2337 }
2338
2339 void GraphicsCache::eraseLastBridgeItem()
2340 {
2341   if (d_bridgelist.empty())
2342     return;
2343
2344   BridgeCacheItem* myitem = *(d_bridgelist.begin());
2345   d_bridgelist.erase(d_bridgelist.begin());
2346
2347   int size = myitem->surface->get_width() * myitem->surface->get_height();
2348   d_cachesize -= myitem->surface->get_depth()/8 * size;
2349
2350   delete myitem->surface;
2351   delete myitem;
2352 }
2353
2354 void GraphicsCache::eraseLastCursorItem()
2355 {
2356   if (d_cursorlist.empty())
2357     return;
2358
2359   CursorCacheItem* myitem = *(d_cursorlist.begin());
2360   d_cursorlist.erase(d_cursorlist.begin());
2361
2362   int size = myitem->surface->get_width() * myitem->surface->get_height();
2363   d_cachesize -= myitem->surface->get_depth()/8 * size;
2364
2365   delete myitem->surface;
2366   delete myitem;
2367 }
2368
2369 void GraphicsCache::eraseLastCityItem()
2370 {
2371   if (d_citylist.empty())
2372     return;
2373
2374   CityCacheItem* myitem = *(d_citylist.begin());
2375   d_citylist.erase(d_citylist.begin());
2376
2377   int size = myitem->surface->get_width() * myitem->surface->get_height();
2378   d_cachesize -= myitem->surface->get_depth()/8 * size;
2379
2380   delete myitem->surface;
2381   delete myitem;
2382 }
2383
2384 void GraphicsCache::eraseLastTowerItem()
2385 {
2386   if (d_towerlist.empty())
2387     return;
2388
2389   TowerCacheItem* myitem = *(d_towerlist.begin());
2390   d_towerlist.erase(d_towerlist.begin());
2391
2392   int size = myitem->surface->get_width() * myitem->surface->get_height();
2393   d_cachesize -= myitem->surface->get_depth()/8 * size;
2394
2395   delete myitem->surface;
2396   delete myitem;
2397 }
2398
2399 void GraphicsCache::eraseLastShipItem()
2400 {
2401   if (d_shiplist.empty())
2402     return;
2403
2404   ShipCacheItem* myitem = *(d_shiplist.begin());
2405   d_shiplist.erase(d_shiplist.begin());
2406
2407   int size = myitem->surface->get_width() * myitem->surface->get_height();
2408   d_cachesize -= myitem->surface->get_depth()/8 * size;
2409
2410   delete myitem->surface;
2411   delete myitem;
2412 }
2413
2414 void GraphicsCache::eraseLastNewLevelItem()
2415 {
2416   if (d_newlevellist.empty())
2417     return;
2418
2419   NewLevelCacheItem* myitem = *(d_newlevellist.begin());
2420   d_newlevellist.erase(d_newlevellist.begin());
2421
2422   int size = myitem->surface->get_width() * myitem->surface->get_height();
2423   d_cachesize -= myitem->surface->get_depth()/8 * size;
2424
2425   delete myitem->surface;
2426   delete myitem;
2427 }
2428
2429 void GraphicsCache::eraseLastExplosionItem()
2430 {
2431   if (d_explosionlist.empty())
2432     return;
2433
2434   ExplosionCacheItem* myitem = *(d_explosionlist.begin());
2435   d_explosionlist.erase(d_explosionlist.begin());
2436
2437   int size = myitem->surface->get_width() * myitem->surface->get_height();
2438   d_cachesize -= myitem->surface->get_depth()/8 * size;
2439
2440   delete myitem->surface;
2441   delete myitem;
2442 }
2443
2444 void GraphicsCache::eraseLastBagItem()
2445 {
2446   if (d_baglist.empty())
2447     return;
2448
2449   BagCacheItem* myitem = *(d_baglist.begin());
2450   d_baglist.erase(d_baglist.begin());
2451
2452   int size = myitem->surface->get_width() * myitem->surface->get_height();
2453   d_cachesize -= myitem->surface->get_depth()/8 * size;
2454
2455   delete myitem->surface;
2456   delete myitem;
2457 }
2458
2459 void GraphicsCache::eraseLastSignpostItem()
2460 {
2461   if (d_signpostlist.empty())
2462     return;
2463
2464   SignpostCacheItem* myitem = *(d_signpostlist.begin());
2465   d_signpostlist.erase(d_signpostlist.begin());
2466
2467   int size = myitem->surface->get_width() * myitem->surface->get_height();
2468   d_cachesize -= myitem->surface->get_depth()/8 * size;
2469
2470   delete myitem->surface;
2471   delete myitem;
2472 }
2473
2474 void GraphicsCache::eraseLastPortItem()
2475 {
2476   if (d_portlist.empty())
2477     return;
2478
2479   PortCacheItem* myitem = *(d_portlist.begin());
2480   d_portlist.erase(d_portlist.begin());
2481
2482   int size = myitem->surface->get_width() * myitem->surface->get_height();
2483   d_cachesize -= myitem->surface->get_depth()/8 * size;
2484
2485   delete myitem->surface;
2486   delete myitem;
2487 }
2488
2489 void GraphicsCache::eraseLastPlantedStandardItem()
2490 {
2491   if (d_plantedstandardlist.empty())
2492     return;
2493
2494   PlantedStandardCacheItem* myitem = *(d_plantedstandardlist.begin());
2495   d_plantedstandardlist.erase(d_plantedstandardlist.begin());
2496
2497   int size = myitem->surface->get_width() * myitem->surface->get_height();
2498   d_cachesize -= myitem->surface->get_depth()/8 * size;
2499
2500   delete myitem->surface;
2501   delete myitem;
2502 }
2503
2504 void GraphicsCache::eraseLastFlagItem()
2505 {
2506   if (d_flaglist.empty())
2507     return;
2508
2509   FlagCacheItem* myitem = *(d_flaglist.begin());
2510   d_flaglist.erase(d_flaglist.begin());
2511
2512   int size = myitem->surface->get_width() * myitem->surface->get_height();
2513   d_cachesize -= myitem->surface->get_depth()/8 * size;
2514
2515   delete myitem->surface;
2516   delete myitem;
2517 }
2518
2519 void GraphicsCache::eraseLastSelectorItem()
2520 {
2521   if (d_selectorlist.empty())
2522     return;
2523
2524   SelectorCacheItem* myitem = *(d_selectorlist.begin());
2525   d_selectorlist.erase(d_selectorlist.begin());
2526
2527   int size = myitem->surface->get_width() * myitem->surface->get_height();
2528   d_cachesize -= myitem->surface->get_depth()/8 * size;
2529
2530   delete myitem->surface;
2531   delete myitem;
2532 }
2533
2534 void GraphicsCache::eraseLastShieldItem()
2535 {
2536   if (d_shieldlist.empty())
2537     return;
2538
2539   ShieldCacheItem* myitem = *(d_shieldlist.begin());
2540   d_shieldlist.erase(d_shieldlist.begin());
2541
2542   int size = myitem->surface->get_width() * myitem->surface->get_height();
2543   d_cachesize -= myitem->surface->get_depth()/8 * size;
2544
2545   delete myitem->surface;
2546   delete myitem;
2547 }
2548
2549 void GraphicsCache::eraseLastProdShieldItem()
2550 {
2551   if (d_prodshieldlist.empty())
2552     return;
2553
2554   ProdShieldCacheItem* myitem = *(d_prodshieldlist.begin());
2555   d_prodshieldlist.erase(d_prodshieldlist.begin());
2556
2557   int size = myitem->surface->get_width() * myitem->surface->get_height();
2558   d_cachesize -= myitem->surface->get_depth()/8 * size;
2559
2560   delete myitem->surface;
2561   delete myitem;
2562 }
2563
2564 void GraphicsCache::eraseLastMoveBonusItem()
2565 {
2566   if (d_movebonuslist.empty())
2567     return;
2568
2569   MoveBonusCacheItem* myitem = *(d_movebonuslist.begin());
2570   d_movebonuslist.erase(d_movebonuslist.begin());
2571
2572   int size = myitem->surface->get_width() * myitem->surface->get_height();
2573   d_cachesize -= myitem->surface->get_depth()/8 * size;
2574
2575   delete myitem->surface;
2576   delete myitem;
2577 }
2578
2579 void GraphicsCache::loadDiplomacyPics()
2580 {
2581   int ts = 30;
2582   std::vector<PixMask* > diplomacypics;
2583   diplomacypics = disassemble_row(File::getMiscFile("various/diplomacy-small.png"), 
2584                              DIPLOMACY_TYPES);
2585   for (unsigned int i = 0; i < DIPLOMACY_TYPES ; i++)
2586     {
2587       if (diplomacypics[i]->get_width() != ts)
2588         PixMask::scale(diplomacypics[i], ts, ts);
2589       d_diplomacypic[0][i] = diplomacypics[i];
2590
2591     }
2592
2593   ts = 50;
2594   diplomacypics = disassemble_row(File::getMiscFile("various/diplomacy-large.png"), 
2595                              DIPLOMACY_TYPES);
2596   for (unsigned int i = 0; i < DIPLOMACY_TYPES ; i++)
2597     {
2598       if (diplomacypics[i]->get_width() != ts)
2599         PixMask::scale(diplomacypics[i], ts, ts);
2600       d_diplomacypic[1][i] = diplomacypics[i];
2601
2602     }
2603 }
2604
2605 void GraphicsCache::loadCursorPics()
2606 {
2607   int ts = 16;
2608
2609   // load the cursor pictures
2610   std::vector<PixMask* > cursorpics;
2611   cursorpics = disassemble_row(File::getMiscFile("various/cursors.png"),
2612                                CURSOR_TYPES);
2613   for (unsigned int i = 0; i < CURSOR_TYPES ; i++)
2614     {
2615       if (cursorpics[i]->get_width() != ts)
2616         PixMask::scale(cursorpics[i], ts, ts);
2617       d_cursorpic[i] = cursorpics[i];
2618     }
2619 }
2620
2621 bool GraphicsCache::loadSelectorImages(std::string filename, guint32 size, std::vector<PixMask* > &images, std::vector<PixMask* > &masks)
2622 {
2623   int num_frames;
2624   num_frames = Gdk::Pixbuf::create_from_file (filename)->get_width() / size;
2625   images = disassemble_row(filename, num_frames, true);
2626   for (int i = 0; i < num_frames; i++)
2627     {
2628       if (images[i]->get_width() != (int)size)
2629         PixMask::scale(images[i], size, size);
2630     }
2631
2632   masks = disassemble_row(filename, num_frames, false);
2633   for (int i = 0; i < num_frames; i++)
2634     {
2635       if (masks[i]->get_width() != (int)size)
2636         PixMask::scale(masks[i], size, size);
2637     }
2638
2639   return true;
2640 }
2641
2642 void GraphicsCache::loadProdShields()
2643 {
2644   //load the production shieldset
2645   int xsize = PRODUCTION_SHIELD_WIDTH;
2646   int ysize = PRODUCTION_SHIELD_HEIGHT;
2647   std::vector<PixMask* > prodshieldpics;
2648   prodshieldpics = disassemble_row
2649     (File::getMiscFile("various/prodshieldset.png"), PRODUCTION_SHIELD_TYPES);
2650   for (unsigned int i = 0; i < PRODUCTION_SHIELD_TYPES; i++)
2651     {
2652       if (prodshieldpics[i]->get_width() != xsize)
2653         PixMask::scale(prodshieldpics[i], xsize, ysize);
2654       d_prodshieldpic[i] = prodshieldpics[i];
2655     }
2656 }
2657
2658 void GraphicsCache::loadMedalPics()
2659 {
2660   //load the medal icons
2661   int ts = 40;
2662   std::vector<PixMask* > medalpics;
2663   medalpics = disassemble_row(File::getMiscFile("various/medals_mask.png"),
2664                                   MEDAL_TYPES);
2665   for (unsigned int i = 0; i < MEDAL_TYPES; i++)
2666     {
2667       if (medalpics[i]->get_width() != ts)
2668         PixMask::scale(medalpics[i], ts, ts);
2669       d_medalpic[0][i] = medalpics[i];
2670     }
2671   medalpics = disassemble_row(File::getMiscFile("various/bigmedals.png"),
2672                               MEDAL_TYPES);
2673   for (unsigned int i = 0; i < MEDAL_TYPES; i++)
2674     d_medalpic[1][i] = medalpics[i];
2675 }
2676
2677 void GraphicsCache::loadNewLevelPics()
2678 {
2679   std::vector<PixMask* > half;
2680   half = disassemble_row(File::getMiscFile("various/hero-newlevel-male.png"), 
2681                          2);
2682   d_newlevel_male = half[0];
2683   d_newlevelmask_male = half[1];
2684   half = disassemble_row(File::getMiscFile("various/hero-newlevel-female.png"), 
2685                          2);
2686   d_newlevel_female = half[0];
2687   d_newlevelmask_female = half[1];
2688 }
2689
2690 void GraphicsCache::loadMoveBonusPics()
2691 {
2692   //load the movement bonus icons
2693   int xsize = MOVE_BONUS_WIDTH;
2694   int ysize = MOVE_BONUS_HEIGHT;
2695   std::vector<PixMask* > movebonuspics;
2696   movebonuspics = disassemble_row(File::getMiscFile("various/movebonus.png"),
2697                                   MOVE_BONUS_TYPES);
2698   for (unsigned int i = 0; i < MOVE_BONUS_TYPES; i++)
2699     {
2700       if (movebonuspics[i]->get_width() != xsize)
2701         PixMask::scale(movebonuspics[i], xsize, ysize);
2702       d_movebonuspic[i] = movebonuspics[i];
2703     }
2704 }
2705
2706 bool GraphicsCache::loadFlagImages(std::string filename, guint32 size, std::vector<PixMask* > &images, std::vector<PixMask* > &masks)
2707 {
2708   images = disassemble_row(filename, FLAG_TYPES, true);
2709   for (unsigned int i = 0; i < FLAG_TYPES; i++)
2710     {
2711       if (images[i]->get_width() != (int)size)
2712         PixMask::scale(images[i], size, size);
2713
2714     }
2715   masks = disassemble_row(filename, FLAG_TYPES, false);
2716   for (unsigned int i = 0; i < FLAG_TYPES; i++)
2717     {
2718       if (masks[i]->get_width() !=(int) size)
2719         PixMask::scale(masks[i], size, size);
2720     }
2721   return true;
2722 }
2723
2724 PixMask* GraphicsCache::getMedalPic(bool large, int type)
2725 {
2726   if (large)
2727     return d_medalpic[1][type];
2728   else
2729     return d_medalpic[0][type];
2730 }
2731
2732 PixMask* GraphicsCache::loadImage(std::string filename, bool alpha)
2733 {
2734   return PixMask::create(filename);
2735 }
2736
2737 PixMask* GraphicsCache::getMiscPicture(std::string picname, bool alpha)
2738 {
2739   return loadImage(File::getMiscFile("/various/" + picname), alpha);
2740 }
2741