1 #include "xyedit.h"
2 #include <iostream>
3 #include <fstream>
4 #include <algorithm>
5 #include "xye.h"
6 using std::pair;
7 using std::max_element;
8 
9 
10 
saveColor(std::ofstream & file,boardelement & o,bool allownocolor=false)11 void saveColor(std::ofstream &file,boardelement &o,bool allownocolor=false)
12 {
13     if(allownocolor && (o.color==EDCO_WHITE)) file << "nocolor='1' ";
14     else switch(o.color)
15     {
16         case EDCO_BLUE: file<<"bc='B' "; break;
17         case EDCO_YELLOW: file<<"bc='Y' "; break;
18         case EDCO_RED: file<<"bc='R' "; break;
19         case EDCO_PURPLE: file<<"bc='P' "; break;
20         default: file<<"bc='G' "; break;
21     }
22 
23 }
24 
25 
saveDirection(std::ofstream & file,boardelement & o)26 void saveDirection(std::ofstream &file,boardelement &o)
27 {
28     switch(o.direction)
29     {
30         case EDITORDIRECTION_UP: file<<"dir='U' "; break;
31         case EDITORDIRECTION_DOWN: file<<"dir='D' "; break;
32         case EDITORDIRECTION_RIGHT: file<<"dir='R' "; break;
33         default: file<<"dir='L' "; break;
34     }
35 
36 }
37 
saveOppositeDirection(std::ofstream & file,boardelement & o)38 void saveOppositeDirection(std::ofstream &file,boardelement &o)
39 {
40     switch(o.direction)
41     {
42         case EDITORDIRECTION_UP: file<<"dir='D' "; break;
43         case EDITORDIRECTION_DOWN: file<<"dir='U' "; break;
44         case EDITORDIRECTION_RIGHT: file<<"dir='L' "; break;
45         default: file<<"dir='R' "; break;
46     }
47 
48 }
49 
50 
saveRound(std::ofstream & file,boardelement & o)51 void saveRound(std::ofstream &file,boardelement &o)
52 {
53     if(o.round) file << "round='1' ";
54 }
55 
56 int savePosition_lastx = -1;
resetSavedPosition()57 void resetSavedPosition()
58 {
59     savePosition_lastx = -1;
60 }
savePosition(std::ofstream & file,int x,int y)61 void savePosition(std::ofstream &file, int x ,int y)
62 {
63     if(x!=savePosition_lastx) {
64         file << "x='"<<x<<"' y='"<<y<<"' ";
65         savePosition_lastx = x;
66     } else {
67         file << "y='"<<y<<"' ";
68     }
69 
70 }
71 
saveLargeBlock(std::ofstream & file,boardelement & o,int x,int y)72 void saveLargeBlock(std::ofstream &file, boardelement &o, int x ,int y)
73 {
74     file <<"<largeblockpart ";
75     savePosition(file,x,y);
76     saveColor(file,o, true);
77     Uint8 flags = getLargeBlockFlagsByVarDir(o.variation, o.direction);
78     const char* dirs = "-U-R-D-L";
79     file<<"sharededges = '";
80     for (int i=1; i<9; i++)
81         if(flags&(1<<i))
82             file<<dirs[i];
83     file<<"' />";
84 
85 
86 }
87 
saveColorFactory(std::ofstream & file,boardelement & o,int x,int y)88 void saveColorFactory(std::ofstream &file, boardelement &o, int x ,int y)
89 {
90     file <<"<factory ";
91     savePosition(file,x,y);
92     switch(o.direction)
93     {
94         case EDITORDIRECTION_UP: file<<"dir='U' swdir='D' "; break;
95         case EDITORDIRECTION_DOWN: file<<"dir='D' swdir='U' "; break;
96         case EDITORDIRECTION_RIGHT: file<<"dir='R' swdir='L' "; break;
97         default: file<<"dir='L' swdir='R' "; break;
98     }
99 
100     saveColor(file,o, false);
101     saveRound(file,o);
102     file<<"kind='";
103     switch(o.variation)
104     {
105         case 0: case 1: case 2: file<<o.variation; break;
106         case 3: file<<4; break;
107         case 4: file<<8; break;
108     }
109 
110     file<<"' />";
111 
112 
113 }
114 
saveDangerFactory(std::ofstream & file,boardelement & o,int x,int y)115 void saveDangerFactory(std::ofstream &file, boardelement &o, int x ,int y)
116 {
117     file <<"<factory ";
118     savePosition(file,x,y);
119     switch(o.direction)
120     {
121         case EDITORDIRECTION_UP: file<<"dir='U' swdir='D' "; break;
122         case EDITORDIRECTION_DOWN: file<<"dir='D' swdir='U' "; break;
123         case EDITORDIRECTION_RIGHT: file<<"dir='R' swdir='L' "; break;
124         default: file<<"dir='L' swdir='R' "; break;
125     }
126 
127     file<<"kind='";
128     switch(o.variation)
129     {
130         case 14:
131             file<<7; break;
132         case 15:
133             file<<6; break;
134         case 16:
135             file<<3; break;
136 
137         default:
138             file<<5<<"' beastkind='"<<o.variation; break;
139     }
140 
141     file<<"' />";
142 
143 
144 }
145 
146 int defaultWallVariation = 0;
saveNormalObject(std::ofstream & file,boardelement & o,int x,int y)147 void saveNormalObject(std::ofstream &file, boardelement &o, int x, int y)
148 {
149     switch(o.type)
150     {
151         case EDOT_NONE : return; //nothing to do
152         case EDOT_BLOCK:
153             switch(o.color)
154             {
155               case EDCO_METAL:
156                 file<<"\t\t<metalblock ";
157                 savePosition(file,x,y);
158                 saveRound(file,o);
159                 file <<"/>\n";
160                 break;
161               case EDCO_WILD:
162                 file<<"\t\t<wild ";
163                 savePosition(file,x,y);
164                 saveRound(file,o);
165                 file <<"/>\n";
166                 break;
167 
168               default:
169                 file<<"\t\t<block ";
170                 savePosition(file,x,y);
171                 saveColor(file,o,true);
172                 saveRound(file,o);
173                 file <<"/>\n";
174             }
175             break;
176         case EDOT_GEM:
177             if(o.color == EDCO_PURPLE)
178             {
179                 file<<"\t\t<star ";
180                 savePosition(file,x,y);
181                 file << "/>\n";
182             }
183             else
184             {
185                 file<<"\t\t<gem ";
186                 savePosition(file,x,y);
187                 saveColor(file,o);
188                 file <<"/>\n";
189             }
190             break;
191 
192         case EDOT_WALL:
193             file<<"\t\t<wall ";
194             savePosition(file,x,y);
195             if(o.round)
196             {
197                 //update memory in case the board wasn't drawn (which may happen when there are multiple levels)
198                 editor::board->updateWallMem(x,XYE_VERT-y-1);
199                 if(o.r1mem) file << "round1='1' ";
200                 if(o.r7mem) file << "round7='1' ";
201                 if(o.r3mem) file << "round3='1' ";
202                 if(o.r9mem) file << "round9='1' ";
203             }
204 
205 
206             if(o.variation != defaultWallVariation) file << "type='"<<o.variation<<"' ";
207 
208             file <<"/>\n";
209             break;
210 
211         case EDOT_TURNER:
212             file<<"\t\t<";
213             if(o.variation) file<<"aclocker ";
214             else file << "clocker ";
215             savePosition(file,x,y);
216             saveRound(file,o);
217             saveColor(file,o,true);
218             file<<"/>\n";
219             break;
220 
221 
222 
223         case EDOT_GEMBLOCK:
224             file<<"\t\t<gemblock ";
225             savePosition(file,x,y);
226             saveColor(file,o);
227             file <<"/>\n";
228             break;
229 
230         case EDOT_EARTH:
231             file << "\t\t<earth ";
232             savePosition(file,x,y);
233             saveRound(file,o);
234             file<<"/>\n";
235             break;
236 
237         case EDOT_MAGNET:
238             file << "\t\t<magnet ";
239             savePosition(file,x,y);
240 
241             if ((o.direction==EDITORDIRECTION_LEFT) ||  (o.direction==EDITORDIRECTION_RIGHT) )
242             {
243                 file << "horz='1' ";
244             }
245 
246             file << "kind='"<<o.variation<<"' ";
247             file<<"/>\n";
248             break;
249 
250         case EDOT_PUSHER:
251             file << "\t\t<pusher ";
252             savePosition(file,x,y);
253             saveDirection(file,o);
254             saveColor(file,o);
255 
256             file<<"/>\n";
257             break;
258 
259         case EDOT_ARROWMAKER:
260             file<<"\t\t<";
261             if(o.variation==0) file << "auto ";
262             else if(o.variation==2) file << "sniper ";
263             else if(o.variation==1) file << "filler ";
264             savePosition(file,x,y);
265             saveDirection(file,o);
266             saveColor(file,o);
267             saveRound(file,o);
268 
269             file<<"/>\n";
270             break;
271 
272         case EDOT_HAZARD: if(o.variation==2) break;
273             file<<"\t\t<";
274             if(o.variation==0) file << "blacky ";
275             else if(o.variation==1) file << "mine ";
276             savePosition(file,x,y);
277             file<<"/>\n";
278             break;
279 
280         case EDOT_BEAST:
281             file<<"\t\t<beast ";
282             savePosition(file,x,y);
283             saveDirection(file,o);
284             file << "kind='"<<o.variation<<"' ";
285 
286             file<<"/>\n";
287             break;
288 
289         case EDOT_TELEPORT:
290             file<<"\t\t<teleport ";
291             savePosition(file,x,y);
292             saveDirection(file,o);
293             file <<"/>\n";break;
294 
295         case EDOT_COLORSYSTEM:
296             if(o.variation==5) //window block:
297             {
298                 file<<"\t\t<window ";
299                 savePosition(file,x,y);
300                 saveColor(file,o);
301                 file<<"/>\n";
302             }
303             else if(o.variation==6) //block on top of area
304             {
305                 file<<"\t\t<block ";
306                 savePosition(file,x,y);
307                 saveColor(file,o);
308                 file<<"/>\n";
309             } else if (o.variation==7) { //wildcard block on top of area
310                 file<<"\t\t<wild ";
311                 savePosition(file,x,y);
312                 file<<"/>\n";
313             }
314             break;
315 
316         case EDOT_BOT:
317             file<<"\t\t<bot ";
318             savePosition(file,x,y);
319             file << "/>\n";
320             break;
321 
322         case EDOT_KEYSYSTEM:
323             file<<"\t\t<";
324             if(o.variation) file<<"lock ";
325             else file<<"key ";
326             savePosition(file,x,y);
327             saveColor(file,o);
328             file << "/>\n";
329             break;
330 
331         case EDOT_NUMBER:
332             file<<"\t\t<timer ";
333             savePosition(file,x,y);
334             saveRound(file,o);
335             saveColor(file,o);
336             file << "val='"<<o.variation<<"' ";
337             file << "/>\n";
338             break;
339 
340 
341         case EDOT_SPECIALBLOCKS:
342             file<<"\t\t<";
343 
344             if (o.variation==0)
345             {
346                 file<<"arrow ";
347                 saveDirection(file,o);
348             }
349             else if (o.variation==1)
350             {
351                 file<<"scroll ";
352                 saveDirection(file,o);
353 
354             }
355             else if(o.variation<=3)
356             {
357                 if( o.variation==2) file << "toggle off='1' ";
358                 else file << "toggle ";
359             }
360             else if (o.variation==4) file << "lblock ";
361             else file << "surprise ";
362             savePosition(file,x,y);
363             saveColor(file,o);
364             saveRound(file,o);
365             file << "/>\n";
366             break;
367         case EDOT_RATTLERHEAD:
368             file<<"\t\t<rattler ";
369             savePosition(file,x,y);
370             saveDirection(file,o);
371             if (o.variation) file << "grow='"<<o.variation<<"' ";
372 
373             file << "/>\n";
374             break;
375 
376         case EDOT_FOOD:
377             file<<"\t\t<rfood ";
378             savePosition(file,x,y);
379             file << "/>\n";
380             break;
381 
382         case EDOT_LARGEBLOCK:
383             file<<"\t\t";
384             saveLargeBlock(file, o, x,y);
385             file<<"\n";
386             break;
387         case EDOT_COLORFACTORY:
388             file<<"\t\t";
389             saveColorFactory(file,o,x,y);
390             file<<"\n";
391             break;
392         case EDOT_DANGERFACTORY:
393             file<<"\t\t";
394             saveDangerFactory(file,o,x,y);
395             file<<"\n";
396             break;
397 
398         case EDOT_PORTAL:
399             // Do nothing.
400             break;
401     }
402 }
403 
savePortals(std::ofstream & file,editorboard * board)404 void savePortals(std::ofstream &file, editorboard *board)
405 {
406     for (int i=0; i<XYE_OBJECT_COLORS+1; i++)
407         if( board->portal_x[i][0] != -1)
408         {
409             int x = board->portal_x[i][0];
410             int y = board->portal_y[i][0];
411             int tx = board->portal_x[i][1];
412             int ty = board->portal_y[i][1];
413             if(tx<0) tx=0;
414             if(ty<0) ty=0;
415             file<<"\t\t<portal ";
416             savePosition(file, x,XYE_VERT-y-1);
417             int ni = i;
418             if ( i == 5 ) {
419                 ni = 4;
420             } else if (i==4) {
421                 ni = 5;
422             }
423 
424             file<<"defcolor='"<<ni<<"' ";
425             file<<"targetx='"<<tx<<"' targety='"<<(XYE_VERT-ty-1)<<"' ";
426             file << "/>\n";
427             if(board->objects[tx][ty].variation == 1)
428             {
429                 file<<"\t\t<portal ";
430                 savePosition(file, tx,XYE_VERT-ty-1);
431                 file<<"defcolor='"<<ni<<"' ";
432                 file<<"targetx='"<<x<<"' targety='"<<(XYE_VERT-y-1)<<"' ";
433                 file << "/>\n";
434 
435             }
436         }
437 
438 }
439 
saveGroundObject(std::ofstream & file,boardelement & o,int x,int y)440 void saveGroundObject(std::ofstream &file,boardelement &o, int x, int y)
441 {
442     switch(o.type)
443     {
444         case EDOT_NONE : return; //nothing to do
445 
446         case EDOT_HAZARD: if(o.variation!=2) break;
447             file<<"\t\t<pit ";
448             savePosition(file,x,y);
449             file<<"/>\n";
450             break;
451 
452         case EDOT_FIREPAD:
453             file<<"\t\t<firepad ";
454             savePosition(file,x,y);
455             file<<"/>\n";
456             break;
457 
458 
459         case EDOT_ONEDIRECTION:
460             if (o.variation >= 2) {
461                 file<<"\t\t<hiddenway ";
462                 Uint32 flags = getHiddenWayFlagsByVariationAndDir(o.variation, o.direction);
463                 string ent = "";
464                 for (int i=2; i<=8; i+=2) {
465                     if ( flags&(1<<i) ) {
466                         ent += ('0'+(char)i);
467                     }
468                 }
469                 file<<"ent='"<<ent<<"' ";
470             } else if(o.variation) {//ground arrow
471                 file<<"\t\t<force ";
472                 saveDirection(file,o);
473             } else {
474                 file<<"\t\t<oneway ";
475                 saveOppositeDirection(file,o);
476             }
477             savePosition(file,x,y);
478 
479             file<<"/>\n";
480             break;
481 
482 
483         case EDOT_COLORSYSTEM:
484             if(o.variation==5) break;
485             file << "\t\t<";
486 
487             switch(o.variation)
488             {
489                 case 0 /*closed door*/: file<<"blockdoor ";break;
490                 case 1 /*open door*/: file<<"blockdoor open='1' ";break;
491                 case 2 /*closed trap*/: file<<"blocktrap ";break;
492                 case 3 /*open trap*/: file<<"blocktrap open='1' ";break;
493                 case 4 /*marked area*/: file<<"marked ";break;
494                 case 6 /*block above area*/: file<<"marked "; break;
495                 case 7 /*wildcard above area*/: file<<"marked "; break;
496 
497             }
498             savePosition(file,x,y);
499             saveColor(file,o);
500             file<<"/>\n";
501             break;
502 
503         case EDOT_HINT:
504             file << "\t\t<hint ";
505             savePosition(file,x,y);
506             file<<">"<<StripXML(o.hint)<<"</hint>";
507             break;
508 
509     }
510 }
511 
save()512 bool editor::save()
513 {
514     if (save(filename, false))
515     {
516          SavedFile=true;
517          return true;
518     }
519     dialogs::makeMessageDialog(editorwindow, string("Unable to save the level file, cannot rewrite ")+string(filename)+".","Ok",onDialogClickDoNothing);
520     return false;
521 }
522 
523 
524 
525 
saveDefault(std::ofstream & file,string tag,editorboard * board,int i)526 void saveDefault( std::ofstream & file, string tag, editorboard*board, int i)
527 {
528      DefaultColorData &cd = board->colors[i];
529      if (! cd.useDefault) {
530          file<<"        <"<<tag<<" ";
531          file<<" color='"<<(i+1)<<"' />" <<endl;
532      }
533 }
534 
saveWallDefault(std::ofstream & file,editorboard * board)535 void saveWallDefault( std::ofstream & file, editorboard*board)
536 {
537     const int MAX_WALL_VARIATIONS = 6;
538     pair<int, int> variationCount[MAX_WALL_VARIATIONS];
539     for (int i=0; i<MAX_WALL_VARIATIONS; i++) {
540         variationCount[i] = make_pair(0, i);
541     }
542     for (int i=0; i<XYE_HORZ; i++) {
543         for (int j=0; j<XYE_VERT; j++) {
544             if (board->objects[i][j].type == EDOT_WALL ) {
545                 variationCount[board->objects[i][j].variation].first++;
546             }
547         }
548     }
549     defaultWallVariation = max_element(variationCount, variationCount + MAX_WALL_VARIATIONS)->second;
550     file<<"        <wall type='"<< defaultWallVariation <<"' ";
551     DefaultColorData &cd = board->colors[EDITOR_COLOR_WALLS];
552     if (! cd.useDefault ) {
553         file<<" color='"<<(EDITOR_COLOR_WALLS+1)<<"' ";
554     }
555 
556     file << " />" <<endl;
557 
558 }
559 
560 
saveColorStuff(std::ofstream & file,editorboard * board)561 void saveColorStuff( std::ofstream & file, editorboard*board)
562 {
563     bool doit = false;
564     for (int i=0; i<TOTAL_EDITOR_COLOR_OPTIONS; i++) {
565         doit |= (! board->colors[i].useDefault );
566     }
567     if (doit) {
568         //first save the palette.
569         file<<"    <palette>"<<endl;
570         for (int i=0; i<TOTAL_EDITOR_COLOR_OPTIONS; i++) {
571             DefaultColorData &cd = board->colors[i];
572             if ( ! cd.useDefault ) {
573                 file << "        <color id='"<<(i+1)<<"'";
574                 file << " red='"<<(int)cd.color.r<<"'";
575                 file << " green='"<<(int)cd.color.g<<"'";
576                 file << " blue='"<<(int)cd.color.b<<"'";
577                 file << " />"<<endl;
578             }
579 
580         }
581         file<<"    </palette>"<<endl;
582     }
583 
584     //now save the defaults...
585     file<<"    <default>"<<endl;
586 
587     //saveDefault(file, "wall", board, EDITOR_COLOR_WALLS);
588     saveWallDefault(file, board);
589     saveDefault(file, "earth", board, EDITOR_COLOR_EARTH);
590     saveDefault(file, "oneway", board, EDITOR_COLOR_DOORS);
591     saveDefault(file, "force", board, EDITOR_COLOR_FORCE);
592 
593     file<<"    </default>"<<endl;
594 
595     if (! board->colors[EDITOR_COLOR_FLOOR].useDefault) {
596         file <<"    <floor><area color = '"<<(EDITOR_COLOR_FLOOR+1)<<"' ";
597         file << "x1='0' x2='29' y1='0' y2='19' /></floor>"<<endl;
598     }
599 
600 
601 }
save(const string & target,bool onlyOneLevel)602 bool editor::save(const string &target, bool onlyOneLevel)
603 {
604     std::ofstream file;
605     file.open (target.c_str(),std::ios::trunc | std::ios::out );
606     if (!file.is_open()) return false; //ouch just halt.
607 
608     int oldcur = editorboard::CurrentLevelNumber();
609     int first = 0;
610     if (onlyOneLevel) {
611         first = oldcur;
612     }
613     editorboard::SaveCopy(board);
614     editorboard::LoadLevelNumber(board, first);
615 
616     file << "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n";
617     file << "<pack>\n<name>"<< StripXML(editorboard::filetitle) <<"</name><author>"<< StripXML(editorboard::author) <<"</author>\n<description>"<< StripXML(editorboard::description) <<"</description>\n";
618 
619     for (int i=first; i<editorboard::CountLevels(); i++) {
620         editorboard::LoadLevelNumber(board, i);
621         file << "\n<level>\n";
622         file << "<title>"<< StripXML(board->title) <<"</title>\n";
623 
624         if(board->hint!="")
625         {
626             file << "<hint>"<< StripXML(board->hint) <<"</hint>\n";
627         }
628         if(board->solution!="")
629         {
630             file << "<solution>"<< StripXML(board->solution) <<"</solution>\n";
631         }
632 
633         if(board->bye!="")
634         {
635             file << "<bye>"<< StripXML(board->bye) <<"</bye>\n";
636         }
637         saveColorStuff(file, board);
638 
639         int j;
640         file << "\t<ground>\n";
641         resetSavedPosition();
642         for (i=0;i<XYE_HORZ;i++) for (j=0;j<XYE_VERT;j++) saveGroundObject(file,editor::board->objects[i][j],i,XYE_VERT-j-1);
643         file << "\t</ground>\n";
644         file << "\t<objects>\n";
645         resetSavedPosition();
646         for (i=0;i<XYE_HORZ;i++) for (j=0;j<XYE_VERT;j++)
647         {
648             saveNormalObject(file,editor::board->objects[i][j],i,XYE_VERT-j-1);
649         }
650         savePortals( file, editor::board);
651 
652 
653         file << "\t</objects>\n";
654 
655 
656         if(editor::board->xye_x>=0)
657         {
658             resetSavedPosition();
659             file << "\t<xye x='"<<editor::board->xye_x<<"' y='"<<(XYE_VERT-editor::board->xye_y-1)<<"' lives='"<<(editor::board->objects[editor::board->xye_x][editor::board->xye_y].variation+1)<<"' />\n";
660         }
661 
662         file << "</level>\n";
663 
664         if (onlyOneLevel) break;
665     }
666 
667     file << "</pack>\n";
668     editorboard::LoadLevelNumber(board, oldcur);
669 
670 
671 
672 
673 
674     file.close();
675  return true;
676 
677 }
678