1 /*
2 * Seven Kingdoms: Ancient Adversaries
3 *
4 * Copyright 1997,1998 Enlight Software Ltd.
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 *
19 */
20
21 //Filename : OR_RANK.CPP
22 //Description : Ranking report
23
24 #include <ODATE.h>
25 #include <OFONT.h>
26 #include <OGAME.h>
27 #include <OCONFIG.h>
28 #include <OVBROWIF.h>
29 #include <ONATION.h>
30 #include <OINFO.h>
31 #include <vga_util.h>
32 #include "gettext.h"
33
34 //------------- Define coordinations -----------//
35
36 enum { NATION_BROWSE_X1 = ZOOM_X1+6,
37 NATION_BROWSE_Y1 = ZOOM_Y1+6,
38 NATION_BROWSE_X2 = ZOOM_X2-6,
39 NATION_BROWSE_Y2 = NATION_BROWSE_Y1+220,
40 };
41
42 enum { NATION_SCORE_X1 = ZOOM_X1+6,
43 NATION_SCORE_Y1 = NATION_BROWSE_Y2+6,
44 NATION_SCORE_X2 = ZOOM_X2-6,
45 NATION_SCORE_Y2 = NATION_SCORE_Y1+150,
46 };
47
48 enum { NATION_GOAL_X1 = ZOOM_X1+6,
49 NATION_GOAL_Y1 = NATION_SCORE_Y2+6,
50 NATION_GOAL_X2 = ZOOM_X2-6,
51 NATION_GOAL_Y2 = NATION_GOAL_Y1+110,
52 };
53
54 enum { PLAY_TIME_X1 = ZOOM_X1+6,
55 PLAY_TIME_X2 = ZOOM_X2-6,
56 };
57
58 //----------- Define static variables ----------//
59
60 static VBrowseIF browse_nation;
61 static int nation_rank_data_array[MAX_RANK_TYPE][MAX_NATION];
62
63 //----------- Define static functions ----------//
64
65 static void put_nation_rec(int recNo, int x, int y, int refreshFlag);
66 static int nation_filter(int recNo=0);
67 static void disp_score();
68 static void disp_goal();
69 static void disp_play_time(int y1);
70 static void put_heading(char justify, int x1, int y1, int x2, int y2, const char *textPtr);
71
72 #define J_L Font::LEFT_JUSTIFY
73 #define J_C Font::CENTER_JUSTIFY
74 #define J_R Font::RIGHT_JUSTIFY
75
76 //--------- Begin of function Info::disp_rank ---------//
77 //
disp_rank(int refreshFlag)78 void Info::disp_rank(int refreshFlag)
79 {
80 set_rank_data(1); // 1-only set those nations that have contact with us
81
82 int x=NATION_BROWSE_X1+9;
83 int y=NATION_BROWSE_Y1+3;
84
85 vga_back.d3_panel_up(NATION_BROWSE_X1, NATION_BROWSE_Y1, NATION_BROWSE_X2, NATION_BROWSE_Y1+32 );
86
87 put_heading( J_L, x , y, x+180, y+29, _("Kingdom") );
88 put_heading( J_C, x+180, y, x+264, y+29, _("Population") );
89 put_heading( J_L, x+264, y, x+332, y+29, _("Military") );
90 put_heading( J_L, x+332, y, x+406, y+29, _("Economy") );
91 put_heading( J_L, x+406, y, x+484, y+29, _("Reputation") );
92 put_heading( J_L, x+484, y, NATION_BROWSE_X2-20, y+29, _("Fryhtan Battling") );
93
94 if( refreshFlag == INFO_REPAINT )
95 {
96 browse_nation.init( NATION_BROWSE_X1, NATION_BROWSE_Y1+34, NATION_BROWSE_X2, NATION_BROWSE_Y2,
97 0, 22, nation_filter(), put_nation_rec, 1 );
98
99 browse_nation.open(browse_nation_recno);
100 }
101 else
102 {
103 browse_nation.paint();
104 browse_nation.open(browse_nation_recno, nation_filter());
105 }
106
107 //----- display score -------//
108
109 disp_score();
110
111 //------ display goal -------//
112
113 if( !game.game_has_ended ) // if the ending screen has already appeared once, don't display the goal
114 {
115 disp_goal();
116 y = NATION_GOAL_Y2+6;
117 }
118 else
119 {
120 y = NATION_GOAL_Y1;
121 }
122
123 //----- display total playing time -----//
124
125 disp_play_time(y);
126 }
127 //----------- End of function Info::disp_rank -----------//
128
129
130 //--------- Begin of static function disp_score ---------//
131 //
disp_score()132 static void disp_score()
133 {
134 int x=NATION_SCORE_X1+6, y=NATION_SCORE_Y1+6;
135
136 static const char* rankStrArray[] =
137 { N_("Population Score"), N_("Military Score"), N_("Economic Score"),
138 N_("Reputation Score"), N_("Fryhtan Battling Score") };
139
140 vga_util.d3_panel_down( NATION_SCORE_X1, NATION_SCORE_Y1, NATION_SCORE_X2, NATION_SCORE_Y2 );
141
142 //------ display individual scores ---------//
143
144 int rankScore, totalScore=0;
145 int viewNationRecno = nation_filter(browse_nation.recno());
146
147 for( int i=0 ; i<MAX_RANK_TYPE ; i++, y+=16 )
148 {
149 rankScore = info.get_rank_score(i+1, viewNationRecno);
150 totalScore += rankScore;
151
152 font_san.put( x , y, _(rankStrArray[i]) );
153 font_san.put( x+300, y, rankScore, 1 );
154 }
155
156 vga_back.bar( x, y, x+340, y+1, V_BLACK );
157 y+=4;
158
159 //-------- display thte total score --------//
160
161 font_san.put( x , y+2, _("Total Score") );
162 font_san.put( x+300, y+2, totalScore, 1 );
163 y+=20;
164
165 vga_back.bar( x, y, x+340, y+1, V_BLACK );
166 y+=4;
167
168 //-------- display the final score ---------//
169
170 int difficultyRating = config.difficulty_rating;
171 int finalScore = totalScore * difficultyRating / 100;
172 String str;
173
174 str = _("Final Score");
175 str += ": ";
176 str += misc.format(totalScore);
177 str += " X ";
178
179 int x2 = font_san.put( x, y+12, str ) + 5;
180
181 str = misc.format(difficultyRating);
182 str += " ";
183 str += _("(Difficulty Rating)");
184
185 font_san.center_put( x2, y+1, x2+156, y+15, str );
186 vga_back.bar( x2 , y+16, x2+156, y+17, V_BLACK );
187 font_san.put( x2+65, y+19, 100 );
188
189 //------- if the player has cheated -------//
190
191 if( nation_array[viewNationRecno]->cheat_enabled_flag )
192 {
193 str = "X 0 ";
194 str += _("(Cheated)");
195 str += " ";
196
197 finalScore = 0;
198 }
199 else
200 {
201 str = "";
202 }
203
204 str += "= ";
205 str += finalScore;
206
207 font_san.put( x2+170, y+12, str);
208
209 y+=36;
210 }
211 //----------- End of static function disp_score -----------//
212
213
214 //--------- Begin of static function disp_goal ---------//
215 //
disp_goal()216 static void disp_goal()
217 {
218 //----- if the ending screen has already appeared once -----//
219
220 if( game.game_has_ended )
221 return;
222
223 //------------------------------------//
224
225 int x=NATION_GOAL_X1+6, y=NATION_GOAL_Y1+6;
226
227 int goalCount = 1 + config.goal_destroy_monster +
228 config.goal_population_flag +
229 config.goal_economic_score_flag +
230 config.goal_total_score_flag;
231
232 vga_util.d3_panel_down( NATION_GOAL_X1, NATION_GOAL_Y1, NATION_GOAL_X2, NATION_GOAL_Y2 );
233
234 //------------------------------------//
235
236 String str;
237
238 if( goalCount > 1 )
239 {
240 if( config.goal_year_limit_flag )
241 {
242 // TRANSLATORS: GOAL: Achieve One of the Following Before <Date>:
243 snprintf( str, MAX_STR_LEN+1, _("GOAL: Achieve One of the Following Before %s:"), date.date_str(info.goal_deadline) );
244 }
245 else
246 {
247 str = _("GOAL: Achieve One of the Following:");
248 }
249 }
250 else
251 {
252 if( config.goal_year_limit_flag )
253 {
254 // TRANSLATORS: GOAL: Defeat All Other Kingdoms Before <Date>.
255 snprintf( str, MAX_STR_LEN+1, _("GOAL: Defeat All Other Kingdoms Before %s."), date.date_str( info.goal_deadline ) );
256 }
257 else
258 {
259 str = _("GOAL: Defeat All Other Kingdoms.");
260 }
261 }
262
263 //--------------------------------------//
264
265 font_san.put( x, y, str );
266
267 y+=18;
268
269 if( goalCount==1 )
270 return;
271
272 //-----------------------------------//
273
274 str = _("Defeat All Other Kingdoms.");
275
276 font_san.put( x, y, str );
277 y+=16;
278
279 //-----------------------------------//
280
281 if( config.goal_destroy_monster )
282 {
283 str = _("Destroy All Fryhtans.");
284
285 font_san.put( x, y, str );
286
287 y+=16;
288 }
289
290 //-----------------------------------//
291
292 if( config.goal_population_flag )
293 {
294 // TRANSLATORS: Achieve a Population of <Number>.
295 snprintf( str, MAX_STR_LEN+1, _("Achieve a Population of %s."), misc.format(config.goal_population) );
296
297 font_san.put( x, y, str );
298
299 y+=16;
300 }
301
302 //-----------------------------------//
303
304 if( config.goal_economic_score_flag )
305 {
306 // TRANSLATORS: Achieve an Economic Score of <Number>.
307 snprintf( str, MAX_STR_LEN+1, _("Achieve an Economic Score of %s."), misc.format(config.goal_economic_score) );
308
309 font_san.put( x, y, str );
310
311 y+=16;
312 }
313
314 //-----------------------------------//
315
316 if( config.goal_total_score_flag )
317 {
318 // TRANSLATORS: Achieve a Total Score of <Number>.
319 snprintf( str, MAX_STR_LEN+1, _("Achieve a Total Score of %s."), misc.format(config.goal_total_score) );
320
321 font_san.put( x, y, str );
322
323 y+=16;
324 }
325 }
326 //----------- End of static function disp_goal -----------//
327
328
329 //--------- Begin of static function disp_play_time ---------//
330 //
disp_play_time(int y1)331 static void disp_play_time(int y1)
332 {
333 vga_util.d3_panel_down( PLAY_TIME_X1, y1, PLAY_TIME_X2, y1+24 );
334
335 String str;
336
337 // TRANSLATORS: Total Playing Time: <Time duration>
338 snprintf( str, MAX_STR_LEN+1, _("Total Playing Time: %s"), info.play_time_str() );
339
340 font_san.put( PLAY_TIME_X1+6, y1+6, str );
341 }
342 //----------- End of static function disp_play_time -----------//
343
344
345 //--------- Begin of function Info::detect_rank ---------//
346 //
detect_rank()347 void Info::detect_rank()
348 {
349 //------- detect nation browser ------//
350
351 if( browse_nation.detect() )
352 {
353 browse_nation_recno = browse_nation.recno();
354 return;
355 }
356 }
357 //----------- End of function Info::detect_rank -----------//
358
359
360 //-------- Begin of static function nation_filter --------//
361 //
362 // This function has dual purpose :
363 //
364 // 1. when <int> recNo is not given :
365 // - return the total no. of nations of this nation
366 //
367 // 2. when <int> recNo is given :
368 // - return the nation recno in nation_array of the given recno.
369 //
nation_filter(int recNo)370 static int nation_filter(int recNo)
371 {
372 int i, nationCount=0;
373 Nation* viewingNation = NULL;
374
375 if( nation_array.player_recno )
376 viewingNation = nation_array[info.viewing_nation_recno];
377
378 for( i=1 ; i<=nation_array.size() ; i++ )
379 {
380 if( nation_array.is_deleted(i) )
381 continue;
382
383 if( i==info.viewing_nation_recno ||
384 !viewingNation ||
385 viewingNation->get_relation(i)->has_contact )
386 {
387 nationCount++;
388 }
389
390 if( recNo && nationCount==recNo )
391 return i;
392 }
393
394 err_when( recNo ); // the recNo is not found, it is out of range
395
396 return nationCount;
397 }
398 //----------- End of static function nation_filter -----------//
399
400
401 //-------- Begin of static function put_nation_rec --------//
402 //
put_nation_rec(int recNo,int x,int y,int refreshFlag)403 static void put_nation_rec(int recNo, int x, int y, int refreshFlag)
404 {
405 int nationRecno = nation_filter(recNo);
406 Nation* nationPtr = nation_array[nationRecno];
407
408 x+=3;
409 y+=5;
410
411 nationPtr->disp_nation_color(x, y+4);
412
413 font_san.put( x+20, y, nationPtr->nation_name() );
414
415 font_san.put( x+210, y, info.get_rank_pos_str(1, nationRecno) );
416 font_san.put( x+270, y, info.get_rank_pos_str(2, nationRecno) );
417 font_san.put( x+352, y, info.get_rank_pos_str(3, nationRecno) );
418 font_san.put( x+435, y, info.get_rank_pos_str(4, nationRecno) );
419 font_san.put( x+500, y, info.get_rank_pos_str(5, nationRecno) );
420 }
421 //----------- End of static function put_nation_rec -----------//
422
423
424 //-------- Begin of function Info::set_rank_data --------//
425 //
426 // <int> onlyHasContact - if this is 1, then only nations
427 // that have contact with the viewing
428 // nation is counted. Otherwise all nations
429 // are counted.
430 //
set_rank_data(int onlyHasContact)431 void Info::set_rank_data(int onlyHasContact)
432 {
433 Nation* viewingNation = NULL;
434 Nation* nationPtr;
435 int rankPos=0;
436
437 if( nation_array.player_recno && !nation_array.is_deleted(info.viewing_nation_recno) )
438 viewingNation = nation_array[info.viewing_nation_recno];
439
440 memset( nation_rank_data_array, 0, sizeof(nation_rank_data_array) );
441
442 for( int i=1 ; i<=nation_array.size() ; i++ )
443 {
444 if( nation_array.is_deleted(i) )
445 continue;
446
447 if( onlyHasContact )
448 {
449 if( viewingNation && !viewingNation->get_relation(i)->has_contact )
450 continue;
451 }
452
453 nationPtr = nation_array[i];
454
455 nation_rank_data_array[0][i-1] = nationPtr->population_rating;
456
457 nation_rank_data_array[1][i-1] = nationPtr->military_rating;
458
459 nation_rank_data_array[2][i-1] = nationPtr->economic_rating;
460
461 nation_rank_data_array[3][i-1] = (int) nationPtr->reputation;
462
463 nation_rank_data_array[4][i-1] = (int) nationPtr->kill_monster_score;
464 }
465 }
466 //----------- End of static function Info::set_rank_data -----------//
467
468
469 const char *rank_num_th[MAX_NATION] =
470 {
471 // TRANSLATORS: Ordinal number for ranking players
472 N_("1st"),
473 N_("2nd"),
474 N_("3rd"),
475 N_("4th"),
476 N_("5th"),
477 N_("6th"),
478 N_("7th"),
479 };
480 //-------- Begin of function Info::get_rank_pos_str --------//
481 //
get_rank_pos_str(int rankType,int nationRecno)482 char* Info::get_rank_pos_str(int rankType, int nationRecno)
483 {
484 static String rank_pos_msg;
485 Nation* viewingNation = NULL;
486 int curNationRankData = nation_rank_data_array[rankType-1][nationRecno-1];
487 int rankPos=1;
488
489 if( nation_array.player_recno && !nation_array.is_deleted(info.viewing_nation_recno) )
490 viewingNation = nation_array[info.viewing_nation_recno];
491
492 for( int i=1 ; i<=nation_array.size() ; i++ )
493 {
494 if( nation_array.is_deleted(i) || i == nationRecno )
495 continue;
496
497 if( viewingNation && !viewingNation->get_relation(i)->has_contact )
498 continue;
499
500 if( nation_rank_data_array[rankType-1][i-1] > curNationRankData ) // if another nation's value is higher than the given nation's value
501 rankPos++;
502 }
503
504 rank_pos_msg = _(rank_num_th[rankPos-1]);
505 return rank_pos_msg;
506 }
507 //----------- End of function Info::get_rank_pos_str -----------//
508
509
510 //-------- Begin of function Info::get_rank_score --------//
511 //
512 // Get the score of the given nation in the given ranking type.
513 //
get_rank_score(int rankType,int nationRecno)514 int Info::get_rank_score(int rankType, int nationRecno)
515 {
516 int maxValue;
517
518 switch( rankType )
519 {
520 case 1: // population
521 maxValue = 100;
522 break;
523
524 case 2: // military strength
525 maxValue = 200;
526 break;
527
528 case 3: // economic strength
529 maxValue = 6000;
530 break;
531
532 case 4: // reputation
533 maxValue = 100; // so the maximum score of the reputation portion is 50 only
534 break;
535
536 case 5: // monsters slain score
537 maxValue = 1000;
538 break;
539 }
540
541 int rankScore = 100 * nation_rank_data_array[rankType-1][nationRecno-1] / maxValue;
542
543 return MAX(0, rankScore);
544 }
545 //----------- End of function Info::get_rank_score -----------//
546
547
548 //-------- Begin of function Info::get_total_score --------//
549 //
550 // Get the score of the given nation.
551 //
get_total_score(int nationRecno)552 int Info::get_total_score(int nationRecno)
553 {
554 int totalScore=0;
555
556 for( int i=0 ; i<MAX_RANK_TYPE ; i++ )
557 {
558 totalScore += get_rank_score(i+1, nationRecno);
559 }
560
561 return totalScore;
562 }
563 //----------- End of function Info::get_total_score -----------//
564
565
566 //-------- Begin of static function put_heading --------//
567 //
put_heading(char justify,int x1,int y1,int x2,int y2,const char * textPtr)568 static void put_heading(char justify, int x1, int y1, int x2, int y2, const char *textPtr)
569 {
570 int dispLines=0;
571 int totalLines=0;
572 font_san.count_line(x1,y1,x2,y2,textPtr,0,dispLines,totalLines);
573 if( dispLines > 1 )
574 font_san.put_paragraph(x1,y1,x2,y2,textPtr,-1,1,1,justify);
575 else if( y1+7<y2 )
576 font_san.put_paragraph(x1,y1+7,x2,y2,textPtr,-1,1,1,justify);
577 }
578 //----------- End of static function put_heading -----------//
579