1 /*
2 baller1.c
3
4 Copyright (C) 1987, 1989 Eckhard Kruse
5 Copyright (C) 2010, 2013 Thomas Huth
6
7 This program is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 /**********************************************************************
22 * B a l l e r b u r g Modul 1 *
23 * Dies ist der Hauptteil von Ballerburg. Die Routinen dieses Teils *
24 * dienen im gro�en und ganzen der Steuerung des Programmes, sowie *
25 * der Ausf�hrung elementarer Grafikoperationen. *
26 **********************************************************************/
27
28 #include <string.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <math.h>
32 #include <locale.h>
33
34 #include "baller1.h"
35 #include "baller2.h"
36 #include "ballergui.h"
37 #include "screen.h"
38 #include "psg.h"
39 #include "market.h"
40 #include "music.h"
41 #include "paths.h"
42 #include "i18n.h"
43
44 #define Min(a,b) ((a)<(b)?(a):(b))
45 #define Max(a,b) ((a)>(b)?(a):(b))
46 #define menu(a) /* wind_update(3-a) */
47 #define hide() /* graf_mouse(256,0) */
48 #define show() /* graf_mouse(257,0) */
49
50 #define COMP_NUM 7
51
52 short mx, my, bt, xy[100],
53 bur[2],bx[2],by[2], ge[2],pu[2],ku[2],vo[2],st[2],kn[2],
54 wx[2],wy[2], *bg, zug,n, p[6], max_rund,
55 *burgen[30], b_anz;
56 static short ws, wc, t_gew[COMP_NUM][COMP_NUM+4];
57 int ftx, fty, ftw, fth; /* Koordinaten von "Fertig" */
58 void *bur_ad;
59 const char *l_nam, *r_nam;
60 int f;
61 char mod, wnd, end, txt[4], an_erl, au_kap;
62
63 int cw[2] = { 2, 2 }; /* Computer strategy */
64 int cx[2] = { 1, 1 }; /* Computer strength */
65
66 /* Computer player names (i.e. the strategies) */
67 const char *cn[COMP_NUM] = {
68 N_("Oaf"), N_("Yokel"), N_("Boor"), N_("Doofus"),
69 N_("Fumbler"), N_("Geezer"), N_("Ruffian")
70 };
71
72 char nsp1[22], nsp2[22]; /* Names of the players */
73
74 ka_t ka[2][10];
75 ft_t ft[2][5];
76
77
78 /**
79 * Initialize internationalization support
80 */
i18n_init(void)81 static void i18n_init(void)
82 {
83 #if HAVE_LIBINTL_H
84 setlocale(LC_ALL, "");
85 bindtextdomain("ballerburg", Paths_GetLocaleDir());
86 textdomain("ballerburg");
87 #endif
88 }
89
90
91 /*****************************************************************************/
main(int argc,char ** argv)92 int main(int argc, char **argv)
93 {
94 Paths_Init(argv[0]);
95 i18n_init();
96
97 scr_init();
98 scr_init_done_button(&ftx, &fty, &ftw, &fth);
99
100 m_laden("baller.mus"); /* Laden der Musikdatei mit Funktion aus music.c */
101
102 bur_ad = malloc(32000); /* Speicher f�r Burgdaten */
103 if (!bur_ad)
104 {
105 puts(_("Not enough memory for loading the castles."));
106 exit(-1);
107 }
108
109 an_erl=1;
110 max_rund=32767;
111 au_kap=1;
112 t_load();
113 burgen_laden();
114
115 psg_audio_init();
116
117 strcpy(nsp1, _("William"));
118 strcpy(nsp2, _("Frederick"));
119 l_nam = nsp1;
120 r_nam = nsp2;
121
122 mod=0; /* Spielmodus ( wer gegen wen ) */
123
124 neues();
125 while ( ein_zug() );
126
127 t_save();
128
129 scr_exit();
130 m_quit();
131 free(bur_ad);
132
133 return 0;
134 }
135
136
137 /**************************** Tabelle ****************************************/
tabelle(void)138 void tabelle(void)
139 {
140 short i,j;
141 void *save_area;
142
143 save_area = scr_save_bg(17, 55, 640-17*2+1, 400-55*2+24+1);
144
145 scr_sf_interior(0);
146 box(17,56, 623,367, 1);
147 box(19,58, 621,365, 1);
148 box(20,59, 620,364, 1);
149 line(108,59, 108,364);
150
151 for (i = 116; i < 584; i += 72)
152 line(i,59,i,364);
153 line(20,84, 620,84);
154 for (i = 92; i < 264; i += 24)
155 line(20,i, 620,i);
156 for (i = 268; i < 364; i += 24)
157 line(20,i, 620,i);
158 for (i = 0; i < COMP_NUM; i++)
159 scr_l_text(124+i*72, 78, _(cn[i]));
160 for (i = 0; i < COMP_NUM; i++)
161 scr_l_text(36, 110+i*24, _(cn[i]));
162
163 scr_sf_interior(2);
164 scr_sf_style(1);
165 for (i = 0; i < COMP_NUM; i++)
166 {
167 for (j = 0; j < COMP_NUM+4; j++)
168 {
169 z_txt(t_gew[i][j]);
170 if (j == COMP_NUM+3 && !t_gew[i][COMP_NUM])
171 {
172 txt[0]=32;
173 txt[1]='-';
174 txt[2]=0;
175 }
176 scr_l_text(140+i*72, 110+j*24+8*(j>=COMP_NUM), txt);
177 if (i == j)
178 box(116+i*72, 92+j*24, 188+i*72, 116+j*24, 1);
179 }
180 }
181
182 scr_l_text(28, 286, _("Games"));
183 scr_l_text(28, 310, _("Total won"));
184 scr_l_text(28, 334, _("Total lost"));
185 scr_l_text(28, 358, _("Won in %"));
186
187 line(20, 59, 108, 84);
188 scr_l_text(36, 80, "-");
189 scr_l_text(88, 72, "+");
190
191 while (bt == 0 && event(1, 0) == 0);
192 while (bt != 0 && event(1, 0) == 0);
193
194 scr_restore_bg(save_area);
195 }
196
197
z_txt(short a)198 void z_txt(short a)
199 {
200 txt[0]=a/100+48;
201 txt[1]=a%100/10+48;
202 txt[2]=a%10+48;
203 if (a<100)
204 {
205 txt[0]=32;
206 if (a<10) txt[1]=32;
207 }
208 }
209
210
211 /******************** Initialisierung vor neuem Spiel ************************/
neues(void)212 void neues(void)
213 {
214 static short pr[6]={ 200,500,400,150,50,50 }; /* Preise zu Beginn */
215 short j;
216
217 wnd=rand()%60-30;
218 st[0]=st[1]=20;
219 kn[0]=kn[1]=0;
220 for ( j=0;j<6;j++ )
221 p[j]=pr[j]*(95+rand()%11)/100;
222 bild();
223 for ( n=0;n<2;n++ )
224 {
225 bg=burgen[bur[n]];
226 wx[n]=n? 639-bg[23]:bg[23];
227 wy[n]=by[n]-bg[24];
228 for ( f=0;f<5; ) ft[n][f++].x=-1;
229 }
230 zug=n=end=0;
231 f=1;
232 }
233
234
235 /************************* Durchf�hren eines Zuges ***************************/
ein_zug(void)236 int ein_zug(void)
237 {
238 short i = 0, fl, a;
239
240 // puts("ein zug ...");
241
242 n=zug&1;
243 fn();
244 kn[n]&=~16;
245 wnd=wnd*9/10+rand()%12-6;
246
247 werdran(1);
248
249 do
250 {
251 fl=0;
252 menu(1);
253 do
254 {
255 if (event(!(mod&(2-n)), 1) != 0)
256 return(0);
257 }
258 while (!bt && !(mod&(2-n)));
259 //printf("ein zug %i %i %i\n", bt, mod, a);
260 menu(0);
261 bg=burgen[bur[n]];
262
263 if ( mod&(2-n) )
264 {
265 hide();
266 i=comp();
267 show();
268 fl=1+(i<0);
269 }
270 else if (mx > ftx && mx < ftx+ftw && my > fty && my < fty+fth)
271 {
272 /* "Fertig"-Knopf wurde gedrueckt */
273 scr_draw_done_button(1);
274 do
275 {
276 event(1, 0);
277 } while (bt);
278 scr_draw_done_button(0);
279 fl=2;
280 }
281 else
282 {
283 for ( i=0;i<10;i++ )
284 if ( ka[n][i].x<=mx && ka[n][i].x+20>=mx && ka[n][i].x!=-1 &&
285 ka[n][i].y>=my && ka[n][i].y-14<=my ) break;
286 if ( i>9 )
287 {
288 if (drin( bg[25],bg[26],bg[31],bg[32],0,mx,my)
289 || drin( bg[27],bg[28],bg[33],bg[34],0,mx,my)
290 || drin( bg[29],bg[30],bg[35],bg[36],0,mx,my))
291 markt();
292 else if (drin( bg[21],bg[22],30,25,0,mx,my))
293 koenig();
294 }
295 else if (pu[n] < 5)
296 {
297 DlgAlert_Notice(_("You don't have enough gunpowder."), _("Cancel"));
298 }
299 else if (ku[n] == 0)
300 {
301 DlgAlert_Notice(_("You don't have any cannonballs left."), _("Cancel"));
302 }
303 else fl=sch_obj(i);
304 }
305 }
306 while ( !fl );
307
308 werdran(0);
309 if ( fl<2 ) schuss(i);
310
311 if ( ~kn[n]&16 ) kn[n]&=~15;
312 rechnen();
313 zug++;
314
315 for ( i=0;i<10;i++ ) if ( ka[n][i].x>-1 ) break;
316 n=zug&1;
317 bg=burgen[bur[n]];
318 for ( a=0;a<10;a++ ) if ( ka[n][a].x>-1 ) break;
319 if ( a==10 && i<10 && bg[40]>vo[n] && ge[n]<p[2]/3 && au_kap &&
320 ft[n][0].x+ft[n][1].x+ft[n][2].x+ft[n][3].x+ft[n][4].x==-5 )
321 end=n+33;
322
323 if ( !end && zug/2>=max_rund )
324 {
325 static int h[2];
326 for (n=0;n<2;n++)
327 {
328 h[n]=ge[n]+pu[n]*p[4]/30+ku[n]*p[5]/2+(wx[n]>-1)*p[3]+vo[n]*4;
329 for (i=0;i<5;i++) if ( ft[n][i].x>-1 ) h[n]+=p[1];
330 for (i=0;i<10;i++) if ( ka[n][i].x>-1 ) h[n]+=p[2];
331 }
332 end=65+(h[1]<h[0]);
333 }
334 if ( end )
335 {
336 ende();
337 menu(1);
338 while (!bt)
339 {
340 if (event(1, 0) != 0)
341 return 0;
342 }
343 neues();
344 menu(0);
345 }
346 return(1);
347 }
348
349
350 /********** Berechnen von Bev�lkerungszuwachs usw. nach jedem Zug ************/
rechnen(void)351 void rechnen(void)
352 {
353 short j;
354 static short pmi[6]={ 98,347,302,102,30,29 }, /* Preisgrenzen */
355 pma[6]={ 302,707,498,200,89,91 },
356 psp[6]={ 10,50,50,20,10,10 }; /* max. Preisschwankung */
357
358 j=st[n];
359 ge[n]+=vo[n]*(j>65? 130-j:j)/(150-rand()%50);
360 vo[n]=vo[n]*(95+rand()%11)/100+(21-j+rand()%9)*(8+rand()%5)/20;
361 if ( vo[n]<0 )
362 {
363 vo[n]=0;
364 end=n+49;
365 }
366
367 for ( j=0;j<5;j++ ) ge[n]+=(40+rand()%31)*(ft[n][j].x>-1);
368 for ( j=0;j<6;j++ )
369 {
370 p[j]+=psp[j]*(rand()%99)/98-psp[j]/2;
371 p[j]=Max(p[j],pmi[j]);
372 p[j]=Min(p[j],pma[j]);
373 }
374 drw_gpk(0);
375 }
376
377
378 /******************************* Spielende ***********************************/
ende(void)379 void ende(void)
380 {
381 char s1[80], s2[80], s3[80];
382 int a, b;
383 int i;
384 const char *loser;
385 int with_s = 0;
386
387 snprintf(s1, sizeof(s1), _("!! %s has won !!"),
388 end&2 ? _(l_nam) : _(r_nam));
389 loser = (end&2) ? _(r_nam) : _(l_nam);
390 if ((end&240) < 48)
391 {
392 a = loser[strlen(loser)-1];
393 with_s = (a=='s' || a=='S');
394 }
395
396 switch ( end&240 )
397 {
398 case 16:
399 if (with_s)
400 snprintf(s2, sizeof(s2), _("( %s' king was hit,"), loser);
401 else
402 snprintf(s2, sizeof(s2), _("( %s's king was hit,"), loser);
403 strcpy(s3, _("and upon hearing this, the people capitulated. )"));
404 break;
405 case 32:
406 if (with_s)
407 snprintf(s2, sizeof(s2), _("( %s' king has capitulated"),
408 loser);
409 else
410 snprintf(s2, sizeof(s2), _("( %s's king has capitulated"),
411 loser);
412 strcpy(s3, _(" because of the hopeless situation. )"));
413 break;
414 case 48:
415 snprintf(s2, sizeof(s2), _("( %s has no folk left. )"), loser);
416 s3[0]=0;
417 break;
418 case 64:
419 strcpy(s2, _("( The limit of maximum rounds has been reached."));
420 snprintf(s3, sizeof(s3), _("%s is worse off. )"), loser);
421 }
422
423 for (a = 0; a < COMP_NUM && strncmp(cn[a], l_nam, 7); a++);
424 for (b = 0; b < COMP_NUM && strncmp(cn[b], r_nam, 7); b++);
425 if (a < COMP_NUM && b < COMP_NUM && a != b)
426 {
427 if (~end&2)
428 {
429 int c;
430 c=a;
431 a=b;
432 b=c;
433 }
434 t_gew[a][b]++;
435 t_gew[b][a]++;
436 t_gew[b][COMP_NUM+2]++;
437 t_gew[a][COMP_NUM+3] = 100 * ++t_gew[a][COMP_NUM+1]
438 / ++t_gew[a][COMP_NUM];
439 t_gew[b][COMP_NUM+3] = 100 * t_gew[b][COMP_NUM+1]
440 / ++t_gew[b][COMP_NUM];
441 }
442
443 scr_color(0x00800000);
444 for (i = 0; i < 8; i++)
445 {
446 short rxy[4];
447 if (i!=7)
448 scr_fillcolor((i*32)<<16);
449 else
450 scr_fillcolor(0xffffff);
451 rxy[0] = 40 + i*8;
452 rxy[1] = 80 + i*8;
453 rxy[2] = 600 - i*8;
454 rxy[3] = 320 - i*8;
455 scr_bar(rxy);
456 }
457
458 scr_l_text(140, 170, s1);
459 scr_l_text(140, 210, s2);
460 scr_l_text(140, 230, s3);
461
462 bt = 0;
463
464 m_musik();
465
466 Giaccess( 0,138 );
467 Giaccess( 0,139 );
468 Giaccess( 0,140 );
469 }
470
471
472 /**
473 * Die Routine m_wait() wird von m_musik() nach jedem 1/96 Takt
474 * aufgerufen.
475 * In diesem Fall macht sie nichts anderes als die eigentliche
476 * Warteschleife aufzurufen. In eigenen Programmen k�nnten Sie hier
477 * w�hrend der Musik zus�tzliche Aktionen ablaufen lassen.
478 */
m_wait(void)479 int m_wait(void)
480 {
481 m_wloop();
482
483 return (event(0, 0) != 0 || bt);
484 }
485
486
487 /** Anzeige des Spielers, der am Zug ist, sowie Darstellung der Windfahnen ***/
werdran(char c)488 void werdran(char c)
489 {
490 char ad[8];
491 int i;
492 short x, y, w, h, c1, s1, c2, s2;
493 double wk,wl;
494
495 /* Anzahl der Spielrunden ausgeben */
496 z_txt(zug/2+1);
497 scr_l_text(332, 395+16, txt);
498
499 if ( c )
500 {
501 x = 5+(629-104)*n; y = 410;
502 w = 104; h = 48;
503
504 /* Wind ausgeben: */
505 ad[0] = ad[5] = 4+28*!wnd-(wnd>0);
506 i = wnd<0? -wnd:wnd;
507 ad[1] = ad[4] = ' ';
508 ad[2] = 48+i/10;
509 ad[3] = 48+i%10;
510 ad[6] = 0;
511 if ( wx[n]<0 )
512 {
513 ad[0]=ad[5]=32;
514 ad[2]=ad[3]='?';
515 }
516 scr_l_text(x+4, y+h+12, _("Wind:"));
517 scr_l_text(x+52, y+h+12, ad);
518
519 c=wnd>0? 1:-1;
520 wk=c*wnd/15.0;
521 wl=wk*.82;
522 if ( wk>1.57 ) wk=1.57;
523 if ( wl>1.57 ) wl=1.57;
524 s1=c*20*sin(wk);
525 c1=20*cos(wk);
526 s2=c*20*sin(wl);
527 c2=20*cos(wl);
528 ws=s1/2.0;
529 ws+=!ws;
530 wc=c1/2.0;
531
532 hide();
533 if ( wx[n]>-1 )
534 {
535 color(1);
536 x+=w/2;
537 line( x,y+h,x,y+5 );
538 line( x+1,y+h,x+1,y+5 );
539 xy[0]=xy[2]=x+1;
540 xy[1]=y+5;
541 xy[3]=y+11;
542 if ( wk<.2 )
543 {
544 xy[0]=x-1;
545 xy[1]=xy[3]=y+5;
546 xy[2]=x+2;
547 }
548 xy[4]=xy[2]+s1;
549 xy[5]=xy[3]+c1;
550 xy[8]=xy[0]+s1;
551 xy[9]=xy[1]+c1;
552 xy[10]=xy[0];
553 xy[11]=xy[1];
554 xy[6] = ((xy[4] + xy[8]) >> 1) + s2;
555 xy[7] = ((xy[5] + xy[9]) >> 1) + c2;
556 scr_pline(6, xy);
557 }
558 fahne();
559 show();
560 }
561 else
562 {
563 hide();
564 clr(5+(629-104)*n,410, 104,48+16);
565 show();
566 }
567 }
568
569
570 /******************* Darstellung der beiden Windfahnen ***********************/
fahne(void)571 void fahne(void)
572 {
573 int m=-1;
574
575 while ( ++m<2 ) if ( wx[m]>-1 )
576 {
577 clr_bg( wx[m]-10,wy[m]-15,20,15 );
578 color(1);
579 line( wx[m],wy[m],wx[m],wy[m]-15 );
580 if ( m==n )
581 {
582 line( wx[m],wy[m]-15,wx[m]+ws,wy[m]-13+wc );
583 line( wx[m],wy[m]-11,wx[m]+ws,wy[m]-13+wc );
584 }
585 }
586 }
587
588
589 /********************** BALLER.TAB laden/speichern ***************************/
t_load(void)590 int t_load(void)
591 {
592 #if 1
593 //printf("t_load does not work yet\n");
594 #else
595 FILE *f_h;
596
597 f_h = fopen("baller.tab", "rb");
598
599 if (!f_h) {
600 perror("t_load");
601 return(1);
602 }
603 fread(&an_erl, 1, 1, f_h);
604 fread(&au_kap, 1, 1, f_h);
605 fread(&max_rund, 2, 1, f_h);
606 fread(t_gew, 1, sizeof(t_gew), f_h);
607
608 fclose(f_h);
609 #endif
610 return(0);
611 }
612
613
t_save(void)614 int t_save(void)
615 {
616 #if 1
617 //printf("t_save not implemented yet\n");
618 #else
619 FILE *f_h;
620
621 f_h = fopen("baller.tab", "wb");
622 if (!f_h) {
623 perror("t_save");
624 return 1;
625 }
626 fwrite(&an_erl, 1, 1, f_h);
627 fwrite(&au_kap, 1, 1, f_h);
628 fwrite(&max_rund, 2, 1, f_h);
629 fwrite(t_gew, 1, sizeof(t_gew), f_h);
630
631 fclose(f_h);
632 #endif
633 return(0);
634 }
635
636
637 /************************* BALLER.DAT laden **********************************/
638
639 /* liest ein char von der Datei */
zeichen(FILE * f_h)640 static char zeichen(FILE *f_h)
641 {
642 char a;
643
644 if (fread(&a, 1, 1, f_h) != 1)
645 {
646 perror("zeichen");
647 exit(-1);
648 }
649
650 return a;
651 }
652
653 /* liest eine Dezimalzahl von der Datei, Remarks werden �berlesen */
rdzahl(FILE * f_h)654 static int rdzahl(FILE *f_h)
655 {
656 char a,sign=1,rem=0; /* wird durch * getoggled, und zeigt damit an, */
657 /* ob man sich in einer Bemerkung befindet */
658 int val=0;
659
660 do
661 if ( (a=zeichen(f_h))=='*' ) rem=!rem;
662 while ((a != '-' && a < '0') || a > '9' || rem);
663
664 if ( a=='-' )
665 {
666 sign=-1;
667 a=zeichen(f_h);
668 }
669 while ( a>='0' && a<='9' )
670 {
671 val*=10;
672 val+=a-'0';
673 a=zeichen(f_h);
674 }
675
676 return( sign*val );
677 }
678
679
burgen_laden(void)680 void burgen_laden(void)
681 {
682 short *a,j;
683 FILE *f_h;
684 char *dat_name;
685
686 dat_name = malloc(FILENAME_MAX);
687 if (!dat_name)
688 {
689 perror("burgen_laden");
690 exit(-1);
691 }
692 snprintf(dat_name, FILENAME_MAX, "%s/baller.dat",
693 Paths_GetDataDir());
694
695 f_h = fopen(dat_name, "rb");
696 free(dat_name); dat_name = NULL;
697 if (!f_h) {
698 /* Try to open in current directory instead */
699 f_h = fopen( "baller.dat", "rb");
700 if (!f_h) {
701 perror("'baller.dat'");
702 exit(-1);
703 }
704 }
705
706 a = (short *)bur_ad;
707 b_anz = 0;
708
709 while ((j=rdzahl(f_h)) != -999
710 && b_anz < (int)(sizeof(burgen)/sizeof(burgen[0])))
711 {
712 burgen[b_anz++]=a;
713 *a++=j;
714 for ( j=0;j<40;j++ ) *a++=rdzahl(f_h);
715 while ( (*a++=rdzahl(f_h))!=-1 );
716 }
717
718 fclose(f_h);
719 }
720
721
722 /* Ermittelt, ob Punkt gesetzt ist */
loc(int x,int y)723 int loc(int x, int y)
724 {
725 int a;
726
727 a = scr_getpixel(x,y);
728 // printf("loc %i %i = 0x%x\n", x,y, a);
729 return ((a&0xff) != 0xff);
730 }
731
line(short x1,short y1,short x2,short y2)732 void line(short x1, short y1, short x2, short y2) /* Zeichnet eine Linie */
733 {
734 xy[0]=x1;
735 xy[1]=y1;
736 xy[2]=x2;
737 xy[3]=y2;
738 scr_pline(2, xy);
739 }
740
box(short x,short y,short x2,short y2,short c)741 void box(short x, short y, short x2, short y2, short c)
742 {
743 color(c);
744 xy[0]=x;
745 xy[1]=y;
746 xy[2]=x2;
747 xy[3]=y2;
748 scr_bar(xy);
749 }
750