1 /*
2  *
3  *   Copyright (c) 1994, 2002, 2003  Johannes Prix
4  *   Copyright (c) 1994, 2002, 2003  Reinhard Prix
5  *
6  *
7  *  This file is part of Freedroid
8  *
9  *  Freedroid is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 2 of the License, or
12  *  (at your option) any later version.
13  *
14  *  Freedroid is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *
19  *  You should have received a copy of the GNU General Public License
20  *  along with Freedroid; see the file COPYING. If not, write to the
21  *  Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
22  *  MA  02111-1307  USA
23  *
24  */
25 
26 /*----------------------------------------------------------------------
27  *
28  * Desc: Everything that has to do with the takeover game of Paradroid
29  * 	is contained in this file.
30  *
31  *----------------------------------------------------------------------*/
32 
33 #define _takeover_c
34 
35 #include "system.h"
36 
37 #include "defs.h"
38 #include "struct.h"
39 #include "global.h"
40 #include "proto.h"
41 #include "takeover.h"
42 #include "map.h"
43 
44 Uint32 cur_time;  		/* current time in ms */
45 
46 /* Class seperation of the blocks */
47 int BlockClass[TO_BLOCKS] = {
48   CONNECTOR,			/* KABEL */
49   NON_CONNECTOR,		/* KABELENDE */
50   CONNECTOR,			/* VERSTAERKER */
51   CONNECTOR,			/* FARBTAUSCHER */
52   CONNECTOR,			/* VERZWEIGUNG_O */
53   NON_CONNECTOR,		/* VERZWEIGUNG_M */
54   CONNECTOR,			/* VERZWEIGUNG_U */
55   NON_CONNECTOR,		/* GATTER_O */
56   CONNECTOR,			/* GATTER_M */
57   NON_CONNECTOR,		/* GATTER_U */
58   NON_CONNECTOR			/* LEER */
59 };
60 
61 /* Probability of the various elements */
62 #define MAX_PROB		100
63 int ElementProb[TO_ELEMENTS] = {
64   100,				/* EL_KABEL */
65   2,				/* EL_KABELENDE */
66   5,				/* EL_VERSTAERKER */
67   5,				/* EL_FARBTAUSCHER: only on last layer */
68   5,				/* EL_VERZWEIGUNG */
69   5				/* EL_GATTER */
70 };
71 
72 
73 int NumCapsules[TO_COLORS] = {
74   0, 0
75 };
76 
77 point LeftCapsulesStart[TO_COLORS] = {
78   { 4, 2*27 },
79   { 2*255 + 2*30 - 10, 2*27 }
80 };
81 
82 point CurCapsuleStart[TO_COLORS] = {
83   { 2*26, 2*19},
84   { 2*255, 2*19}
85 };
86 
87 point PlaygroundStart[TO_COLORS] = {
88   { 2*33, 2*26},
89   { 2*159, 2*26}
90 };
91 
92 point DruidStart[TO_COLORS] = {
93   { 2*40, -4},
94   { 2*220, -4}
95 };
96 
97 /* Offset of the left/right "grounds" and the "column" */
98 point TO_LeftGroundStart = 	{ 2*10, 2*15 };
99 point TO_ColumnStart = 		{ 2*136, 2*27};
100 point TO_LeaderBlockStart = 	{ 2*129, 2*8};
101 point TO_RightGroundStart = 	{ 2*255, 2*15};
102 
103 SDL_Rect TO_LeaderLed = { 2*136, 2*11, 2*16, 2*19};
104 SDL_Rect TO_FillBlock = { 0, 0, 2*16, 2*7 };
105 SDL_Rect TO_ElementRect = { 0, 0, 2*32, 2*8 };
106 SDL_Rect TO_CapsuleRect = { 0, 0, 2*7, 2*8};
107 SDL_Rect TO_GroundRect = { 0, 0, 2*23, 2*8 };
108 SDL_Rect TO_ColumnRect = { 0, 0, 2*30, 2*8 };
109 
110 
111 int CapsuleCurRow[TO_COLORS] = { 0, 0 };
112 
113 
114 int LeaderColor = GELB;		/* momentary leading color */
115 int YourColor = GELB;
116 int OpponentColor = VIOLETT;
117 int OpponentType;		/* The druid-type of your opponent */
118 int DroidNum;
119 
120 /* the display  column */
121 int DisplayColumn[NUM_LINES] = {
122   GELB, VIOLETT, GELB, VIOLETT, GELB, VIOLETT, GELB, VIOLETT, GELB, VIOLETT,
123   GELB, VIOLETT
124 };
125 
126 
127 SDL_Color to_bg_color = {130,130,130};
128 
129 playground_t ToPlayground;
130 playground_t ActivationMap;
131 playground_t CapsuleCountdown;
132 
133 /*-----------------------------------------------------------------
134  * @Desc: play takeover-game against a druid
135  *
136  * @Ret: TRUE/FALSE:  user has won/lost
137  *
138  *-----------------------------------------------------------------*/
139 int
Takeover(int enemynum)140 Takeover (int enemynum)
141 {
142   int row;
143   int FinishTakeover = FALSE;
144   static int RejectEnergy = 0;	/* your energy if you're rejected */
145   char *message;
146   SDL_Rect buf;
147   Uint32 now;
148 
149   /* Prevent distortion of framerate by the delay coming from
150    * the time spend in the menu.
151    */
152   Activate_Conservative_Frame_Computation ();
153 
154   // release fire keys
155   SpacePressedR();
156   MouseLeftPressedR();
157 
158   // Takeover game always uses Classic User_Rect:
159   Copy_Rect (User_Rect, buf);
160   Copy_Rect (Classic_User_Rect, User_Rect);
161 
162   DisplayBanner (NULL, NULL,  BANNER_FORCE_UPDATE );
163 
164   Fill_Rect (User_Rect, to_bg_color);
165 
166   Me.status = MOBILE; /* the new status _after_ the takeover game */
167 
168   SDL_ShowCursor (SDL_DISABLE); // no mouse-cursor in takeover game!
169 
170   show_droid_info ( Me.type, -1 , 0);
171   show_droid_portrait (Cons_Droid_Rect, Me.type, DROID_ROTATION_TIME, UPDATE);
172   while (!FirePressedR())
173     show_droid_portrait (Cons_Droid_Rect, Me.type, DROID_ROTATION_TIME, 0);
174 
175   show_droid_info ( AllEnemys[enemynum].type, -2 ,0);
176   show_droid_portrait (Cons_Droid_Rect,  AllEnemys[enemynum].type, DROID_ROTATION_TIME, UPDATE);
177   while (!FirePressedR())
178     show_droid_portrait (Cons_Droid_Rect,  AllEnemys[enemynum].type, DROID_ROTATION_TIME, 0);
179 
180   SDL_BlitSurface (takeover_bg_pic, NULL, ne_screen, NULL);
181   DisplayBanner (NULL, NULL,  BANNER_FORCE_UPDATE );
182 
183   while (!FinishTakeover)
184     {
185       /* Init Color-column and Capsule-Number for each opponenet and your color */
186       for (row = 0; row < NUM_LINES; row++)
187 	{
188 	  DisplayColumn[row] = (row % 2);
189 	  CapsuleCountdown[GELB][0][row] = -1;
190 	  CapsuleCountdown[VIOLETT][0][row] = -1;
191 	}			/* for row */
192 
193       YourColor = GELB;
194       OpponentColor = VIOLETT;
195 
196       CapsuleCurRow[GELB] = 0;
197       CapsuleCurRow[VIOLETT] = 0;
198 
199       DroidNum = enemynum;
200       OpponentType = AllEnemys[enemynum].type;
201       NumCapsules[YOU] = 3 + ClassOfDruid (Me.type);
202       NumCapsules[ENEMY] = 4 + ClassOfDruid (OpponentType);
203 
204       InventPlayground ();
205 
206       ShowPlayground ();
207 
208       ChooseColor ();
209 
210       PlayGame ();
211 
212       /* Ausgang beurteilen und returnen */
213       if (InvincibleMode || (LeaderColor == YourColor))
214 	{
215 	  Takeover_Game_Won_Sound ();
216 	  if (Me.type == DRUID001)
217 	    {
218 	      RejectEnergy = Me.energy;
219 	      PreTakeEnergy = Me.energy;
220 	    }
221 
222 	  // We provide some security agains too high energy/health values gained
223 	  // by very rapid successions of successful takeover attempts
224 	  if (Me.energy > Druidmap[DRUID001].maxenergy) Me.energy = Druidmap[DRUID001].maxenergy;
225 	  if (Me.health > Druidmap[DRUID001].maxenergy) Me.health = Druidmap[DRUID001].maxenergy;
226 
227 	  // We allow to gain the current energy/full health that was still in the
228 	  // other droid, since all previous damage must be due to fighting damage,
229 	  // and this is exactly the sort of damage can usually be cured in refreshes.
230 	  Me.energy += AllEnemys[enemynum].energy;
231 	  Me.health += Druidmap[OpponentType].maxenergy;
232 
233 	  Me.type = AllEnemys[enemynum].type;
234 
235 	  RealScore += Druidmap[OpponentType].score;
236 
237 	  DeathCount += OpponentType * OpponentType;   // quadratic "importance", max=529
238 
239 	  AllEnemys[enemynum].status = OUT; // removed droid silently (no blast!)
240 
241 	  if (LeaderColor != YourColor)	/* only won because of InvincibleMode */
242 	    message = "You cheat";
243 	  else				/* won the proper way */
244 	    message = "Complete";
245 
246 	  FinishTakeover = TRUE;
247 	}				/* LeaderColor == YourColor */
248       else if (LeaderColor == OpponentColor)
249 	{
250 	  // you lost, but enemy is killed too --> blast it!
251 	  AllEnemys[enemynum].energy = -1.0;  /* to be sure */
252 
253 	  Takeover_Game_Lost_Sound ();
254 	  if (Me.type != DRUID001)
255 	    {
256 	      message = "Rejected";
257 	      Me.type = DRUID001;
258 	      Me.energy = RejectEnergy;
259 	    }
260 	  else
261 	    {
262 	      message = "Burnt Out";
263 	      Me.energy = 0;
264 	    }
265 	  FinishTakeover = TRUE;
266 	}			/* LeadColor == OpponentColor */
267       else
268 	{
269 	  Takeover_Game_Deadlock_Sound ();
270 	  message = "Deadlock";
271 	}			/* LeadColor == REMIS */
272 
273       DisplayBanner (message, NULL , 0 );
274       ShowPlayground ();
275       now = SDL_GetTicks();
276       while ((!FirePressedR()) && (SDL_GetTicks() - now < SHOW_WAIT) ) SDL_Delay(1);
277 
278     }	/* while !FinishTakeover */
279 
280   // restore User_Rect
281   Copy_Rect (buf, User_Rect);
282 
283   ClearGraphMem();
284   SDL_Flip(ne_screen);
285 
286   if (LeaderColor == YourColor)
287     return TRUE;
288   else
289     return FALSE;
290 
291 } /* Takeover() */
292 
293 
294 /*@Function============================================================
295 @Desc: ChooseColor():	Countdown zum Waehlen der Farbe
296 
297 @Ret: void
298 @Int:
299 * $Function----------------------------------------------------------*/
300 void
ChooseColor(void)301 ChooseColor (void)
302 {
303   int countdown = 100;  /* duration in 1/10 seconds given for color choosing */
304   int ColorChosen = FALSE;
305   char count_text[80];
306 
307   Uint32 prev_count_tick, count_tick_len;
308 
309   count_tick_len = 100; 	/* countdown in 1/10 second steps */
310 
311   prev_count_tick = SDL_GetTicks ();
312 
313   ResetMouseWheel ();  // forget about previous wheel events
314 
315   while (!ColorChosen)
316     {
317       if (RightPressedR() || WheelDownPressed())
318 	{
319 	  if (YourColor != VIOLETT) MoveMenuPositionSound();
320 	  YourColor = VIOLETT;
321 	  OpponentColor = GELB;
322 	}
323       if (LeftPressedR() || WheelUpPressed())
324 	{
325 	  if (YourColor != GELB) MoveMenuPositionSound();
326 	  YourColor = GELB;
327 	  OpponentColor = VIOLETT;
328 	}
329 
330       if (FirePressedR())
331 	{
332 	  ColorChosen = TRUE;
333 	}
334 
335       /* wait for next countdown tick */
336       if ( SDL_GetTicks() >= prev_count_tick + count_tick_len )
337 	{
338 	  prev_count_tick += count_tick_len; /* set for next tick */
339 	  countdown--;		/* Count down */
340 	  sprintf (count_text, "Color-%d", countdown);
341 
342 	  DisplayBanner (count_text, NULL , 0);
343 	  ShowPlayground ();
344 	}
345 
346 
347       if (countdown == 0)
348 	ColorChosen = TRUE;
349 
350     } /* while(!ColorChosen) */
351 
352   return;
353 
354 } /* ChooseColor() */
355 
356 
357 /*-----------------------------------------------------------------
358  * @Desc: the acutal Takeover game-playing is done here
359  *
360  *
361  *-----------------------------------------------------------------*/
362 void
PlayGame(void)363 PlayGame (void)
364 {
365   int countdown = 100;   /* lenght of Game in 1/10 seconds */
366   char count_text[80];
367   int FinishTakeover = FALSE;
368   int row;
369 
370   Uint32 prev_count_tick, count_tick_len;  /* tick vars for count-down */
371   Uint32 prev_move_tick, move_tick_len;    /* tick vars for motion */
372   Uint32 last_movekey_time, wait_move_ticks = 110;    /* number of ticks to wait before "key-repeat" */
373 
374   int up, down, set;
375   int up_counter, down_counter;
376   int wheel_up, wheel_down;
377 
378   count_tick_len = 100;   /* countdown in 1/10 second steps */
379   move_tick_len  = 60;    /* allow motion at this tick-speed in ms */
380 
381   up = down = set = FALSE;
382   up_counter = down_counter = 0;
383   wheel_up = wheel_down = 0;
384 
385   prev_count_tick = prev_move_tick = SDL_GetTicks (); /* start tick clock */
386 
387   ResetMouseWheel ();  // forget about previous wheel events
388 
389   CountdownSound();
390   while (!FinishTakeover)
391     {
392       cur_time = SDL_GetTicks ();
393 
394       /*
395        * here we register if there have been key-press events in the
396        * "waiting period" between move-ticks :
397        */
398       if ( !up && UpPressed () )
399 	{
400 	  up = TRUE;
401 	  last_movekey_time = SDL_GetTicks();
402 	}
403       if (!down && DownPressed() )
404 	{
405 	  down = TRUE;
406 	  last_movekey_time = SDL_GetTicks();
407 	}
408 
409       set  = set  || (SpacePressed() || MouseLeftPressed());
410 
411       if (WheelUpPressed()) wheel_up ++;
412       if (WheelDownPressed()) wheel_down ++;
413 
414       /* allow for a WIN-key that give immedate victory */
415       if ( KeyIsPressedR ('w') && CtrlPressed() && AltPressed() )
416 	{
417 	  LeaderColor = YourColor;   /* simple as that */
418 	  return;  /* leave now, to avoid changing of LeaderColor! */
419 	}
420 
421       if ( cur_time > prev_count_tick + count_tick_len ) /* time to count 1 down */
422 	{
423 	  prev_count_tick += count_tick_len;  /* set for next countdown tick */
424 	  countdown--;
425 	  sprintf (count_text, "Finish-%d", countdown);
426 	  DisplayBanner (count_text, NULL , 0 );
427 
428 	  if (countdown && (countdown%10 == 0) ) CountdownSound();
429 	  if (countdown == 0)
430 	    {
431 	      EndCountdownSound();
432 	      FinishTakeover = TRUE;
433 	    }
434 
435 	  AnimateCurrents ();  /* do some animation on the active cables */
436 
437 	} /* if (countdown_tick has occurred) */
438 
439 
440       /* time for movement */
441       if ( cur_time > prev_move_tick + move_tick_len )
442 	{
443 	  prev_move_tick += move_tick_len; /* set for next motion tick */
444 	  EnemyMovements ();
445 
446 	  if (wheel_up || (up && (SDL_GetTicks() - last_movekey_time > wait_move_ticks)))
447 	    {
448 	      CapsuleCurRow[YourColor]--;
449 	      if (CapsuleCurRow[YourColor] < 1)
450 		CapsuleCurRow[YourColor] = NUM_LINES;
451 
452 	      if (!UpPressed()) up = FALSE;
453 	      if (wheel_up) wheel_up --;
454 	    }
455 	  if (wheel_down || (down && (SDL_GetTicks() - last_movekey_time > wait_move_ticks)))
456 	    {
457 	      CapsuleCurRow[YourColor]++;
458 	      if (CapsuleCurRow[YourColor] > NUM_LINES)
459 		CapsuleCurRow[YourColor] = 1;
460 
461 	      if (!DownPressed()) down = FALSE;
462 	      if (wheel_down) wheel_down --;
463 	    }
464 
465 	  if ( set && (NumCapsules[YOU] > 0))
466 	    {
467 	      set = FALSE;
468 	      row = CapsuleCurRow[YourColor] - 1;
469 	      if ((row >= 0) &&
470 		  (ToPlayground[YourColor][0][row] != KABELENDE) &&
471 		  (ActivationMap[YourColor][0][row] == INACTIVE))
472 		{
473 		  NumCapsules[YOU]--;
474 		  CapsuleCurRow[YourColor] = 0;
475 		  ToPlayground[YourColor][0][row] = VERSTAERKER;
476 		  ActivationMap[YourColor][0][row] = ACTIVE1;
477 		  CapsuleCountdown[YourColor][0][row] = CAPSULE_COUNTDOWN * 2;
478 
479 		  Takeover_Set_Capsule_Sound ();
480 		}	/* if (row > 0 && ... ) */
481 	    } /* if ( set ) */
482 
483 	  ProcessCapsules ();	/* count down the lifetime of the capsules */
484 
485 	  ProcessPlayground ();
486 	  ProcessPlayground ();
487 	  ProcessPlayground ();
488 	  ProcessPlayground ();	/* this has to be done several times to be sure */
489 
490 	  ProcessDisplayColumn ();
491 
492 	} /* if (motion_tick has occurred) */
493 
494       ShowPlayground ();
495 
496     }	/* while !FinishTakeover */
497 
498   /* Schluss- Countdown */
499   countdown = CAPSULE_COUNTDOWN;
500 
501   while (countdown--)
502     {
503       while ( SDL_GetTicks() < prev_count_tick + count_tick_len ) ;
504       prev_count_tick += count_tick_len;
505       ProcessCapsules ();	/* count down the lifetime of the capsules */
506       ProcessCapsules ();	/* do it twice this time to be faster */
507       AnimateCurrents ();
508       ProcessPlayground ();
509       ProcessPlayground ();
510       ProcessPlayground ();
511       ProcessPlayground ();	/* this has to be done several times to be sure */
512       ProcessDisplayColumn ();
513       ShowPlayground ();
514 
515     }	/* while (countdown) */
516 
517     return;
518 
519 } /* PlayGame() */
520 
521 /*-----------------------------------------------------------------
522  * @Desc: animiert Gegner beim Uebernehm-Spiel
523  *
524  * @Ret: void
525  * @Int:
526  *-----------------------------------------------------------------*/
527 void
EnemyMovements(void)528 EnemyMovements (void)
529 {
530   static int Actions = 3;
531   static int MoveProbability = 100;
532   static int TurnProbability = 10;
533   static int SetProbability = 80;
534 
535   int action;
536   static int direction = 1;	/* start with this direction */
537   int row = CapsuleCurRow[OpponentColor] - 1;
538 
539   if (NumCapsules[ENEMY] == 0)
540     return;
541 
542 
543   action = MyRandom (Actions);
544   switch (action)
545     {
546     case 0:			/* Move along */
547       if (MyRandom (100) <= MoveProbability)
548 	{
549 	  row += direction;
550 	  if (row > NUM_LINES - 1)
551 	    row = 0;
552 	  if (row < 0)
553 	    row = NUM_LINES - 1;
554 	}
555       break;
556 
557     case 1:			/* Turn around */
558       if (MyRandom (100) <= TurnProbability)
559 	{
560 	  direction *= -1;
561 	}
562       break;
563 
564     case 2:			/* Try to set  capsule */
565       if (MyRandom (100) <= SetProbability)
566 	{
567 	  if ((row >= 0) &&
568 	      (ToPlayground[OpponentColor][0][row] != KABELENDE) &&
569 	      (ActivationMap[OpponentColor][0][row] == INACTIVE))
570 	    {
571 	      NumCapsules[ENEMY]--;
572 	      Takeover_Set_Capsule_Sound ();
573 	      ToPlayground[OpponentColor][0][row] = VERSTAERKER;
574 	      ActivationMap[OpponentColor][0][row] = ACTIVE1;
575 	      CapsuleCountdown[OpponentColor][0][row] = CAPSULE_COUNTDOWN;
576 	      row = -1;		/* For the next capsule: startpos */
577 	    }
578 	} /* if MyRandom */
579 
580       break;
581 
582     default:
583       break;
584 
585     }	/* switch action */
586 
587   CapsuleCurRow[OpponentColor] = row + 1;
588 
589   return;
590 }	/* EnemyMovements */
591 
592 /*@Function============================================================
593  * read in takeover game elements. Frees previous SDL-surfaces if
594  * they were allocated, this allows to used this fct also for theme-switching
595  *
596  *
597  *-----------------------------------------------------------------*/
598 int
GetTakeoverGraphics(void)599 GetTakeoverGraphics (void)
600 {
601   int i,j;
602   int curx = 0, cury = 0;
603   SDL_Rect tmp;
604   SDL_Surface* TempLoadSurface;
605 
606   Set_Rect (tmp, User_Rect.x, User_Rect.y, 0, 0);
607 
608   FreeIfUsed(to_blocks);   /* this happens when we do theme-switching */
609 
610   TempLoadSurface = IMG_Load (find_file (TO_BLOCK_FILE, GRAPHICS_DIR, USE_THEME, CRITICAL));
611   to_blocks = SDL_DisplayFormatAlpha( TempLoadSurface ); // the surface is converted
612   SDL_FreeSurface ( TempLoadSurface );
613 
614   /* Set the fill-blocks */
615   for (i=0; i<NUM_FILL_BLOCKS; i++,curx += TO_FillBlock.w + 2)
616     Set_Rect (FillBlocks[i], curx, cury, TO_FillBlock.w, TO_FillBlock.h);
617 
618   /* Set the capsule Blocks */
619   for (i = 0; i < NUM_CAPS_BLOCKS; i++, curx += TO_CapsuleRect.w + 2)
620     Set_Rect (CapsuleBlocks[i], curx, cury, TO_CapsuleRect.w, TO_CapsuleRect.h-2);
621 
622   curx = 0;
623   cury += TO_FillBlock.h + 2;
624 
625   /* get the game-blocks */
626 
627   for (j = 0; j < 2*NUM_PHASES; j++)
628     {
629       for (i = 0; i < TO_BLOCKS; i++)
630 	{
631 	  Set_Rect (ToGameBlocks[j*TO_BLOCKS+i], curx, cury, TO_ElementRect.w,TO_ElementRect.h);
632 	  curx += TO_ElementRect.w + 2;
633 	}
634       curx = 0;
635       cury += TO_ElementRect.h + 2;
636     }
637 
638   /* Get the ground, column and leader blocks */
639   for (i = 0; i < NUM_GROUND_BLOCKS; i++)
640     {
641       Set_Rect (ToGroundBlocks[i], curx, cury, TO_GroundRect.w, TO_GroundRect.h);
642       curx += TO_GroundRect.w + 2;
643     }
644   cury += TO_GroundRect.h + 2;
645   curx = 0;
646 
647   Set_Rect (ToColumnBlock, curx, cury, TO_ColumnRect.w, TO_ColumnRect.h);
648 
649   curx += TO_ColumnRect.w + 2;
650 
651   Set_Rect (ToLeaderBlock, curx, cury, 2*TO_LeaderLed.w-4, TO_LeaderLed.h);
652 
653   return(OK);
654 }				// int GetTakeoverGraphics(void)
655 
656 /*-----------------------------------------------------------------
657  * @Desc: prepares _and displays_ the current Playground
658  *
659  *   NOTE: this function should only change the USERFENSTER part
660  *         so that we can do Infoline-setting before this
661  *
662  * @Ret: void
663  *
664  *-----------------------------------------------------------------*/
665 void
ShowPlayground(void)666 ShowPlayground (void)
667 {
668   int i, j;
669   int color, player;
670   int block;
671   int xoffs, yoffs;
672   SDL_Rect dst;
673   SDL_Rect bak;
674 
675 
676   xoffs = Classic_User_Rect.x;
677   yoffs = Classic_User_Rect.y;
678 
679   //  SDL_SetColorKey (ne_screen, 0, 0);
680   //  SDL_SetClipRect (ne_screen , &User_Rect);
681   SDL_SetClipRect (ne_screen , NULL);
682 
683   //  Fill_Rect (User_Rect, to_bg_color);
684   SDL_BlitSurface (takeover_bg_pic, &User_Rect, ne_screen, &User_Rect);
685 
686   PutInfluence (xoffs + DruidStart[YourColor].x, yoffs + DruidStart[YourColor].y);
687 
688   if (AllEnemys[DroidNum].status != OUT)
689     PutEnemy (DroidNum, xoffs + DruidStart[!YourColor].x, yoffs + DruidStart[!YourColor].y);
690 
691   Set_Rect (dst, xoffs + TO_LeftGroundStart.x, yoffs + TO_LeftGroundStart.y, User_Rect.w, User_Rect.h);
692 
693   SDL_BlitSurface (to_blocks, &ToGroundBlocks[GELB_OBEN], ne_screen, &dst);
694 
695   dst.y += TO_GroundRect.h;
696 
697   for (i = 0; i < 12; i++)
698     {
699       SDL_BlitSurface (to_blocks, &ToGroundBlocks[GELB_MITTE], ne_screen, &dst);
700 
701       dst.y += TO_GroundRect.h;
702     }				/* for i=1 to 12 */
703 
704   SDL_BlitSurface (to_blocks, &ToGroundBlocks[GELB_UNTEN], ne_screen, &dst);
705 
706 
707   /* Mittlere Saeule */
708   Set_Rect (dst, xoffs + TO_LeaderBlockStart.x, yoffs + TO_LeaderBlockStart.y, 0, 0);
709   SDL_BlitSurface (to_blocks, &ToLeaderBlock, ne_screen, &dst);
710 
711   dst.y += TO_LeaderLed.h;
712   for (i = 0; i < 12; i++, dst.y += TO_ColumnRect.h)
713     SDL_BlitSurface (to_blocks, &ToColumnBlock, ne_screen, &dst);
714 
715 
716   /* rechte Saeule */
717   Set_Rect (dst, xoffs + TO_RightGroundStart.x, yoffs + TO_RightGroundStart.y, 0, 0);
718 
719   SDL_BlitSurface (to_blocks, &ToGroundBlocks[VIOLETT_OBEN], ne_screen, &dst);
720   dst.y += TO_GroundRect.h;
721 
722   for (i = 0; i < 12; i++, dst.y += TO_GroundRect.h)
723     SDL_BlitSurface (to_blocks, &ToGroundBlocks[VIOLETT_MITTE], ne_screen, &dst);
724 
725   SDL_BlitSurface (to_blocks, &ToGroundBlocks[VIOLETT_UNTEN], ne_screen, &dst);
726 
727   /* Fill the Leader-LED with its color */
728   Set_Rect (dst, xoffs + TO_LeaderLed.x, yoffs + TO_LeaderLed.y, 0, 0);
729   SDL_BlitSurface (to_blocks, &FillBlocks[LeaderColor], ne_screen, &dst);
730   dst.y += TO_FillBlock.h;
731   SDL_BlitSurface (to_blocks, &FillBlocks[LeaderColor], ne_screen, &dst);
732 
733   /* Fill the Display Column with its leds */
734   for (i = 0; i < NUM_LINES; i++)
735     {
736       Set_Rect (dst, xoffs + TO_ColumnStart.x, yoffs + TO_ColumnStart.y + i*TO_ColumnRect.h, 0, 0);
737       SDL_BlitSurface (to_blocks, &FillBlocks[DisplayColumn[i]], ne_screen, &dst);
738     }
739 
740   /* Show the yellow playground */
741   for (i = 0; i < NUM_LAYERS - 1; i++)
742     for (j = 0; j < NUM_LINES; j++)
743       {
744 	Set_Rect (dst, xoffs + PlaygroundStart[GELB].x + i * TO_ElementRect.w,
745 		  yoffs + PlaygroundStart[GELB].y + j * TO_ElementRect.h, 0, 0);
746 	block = ToPlayground[GELB][i][j] + ActivationMap[GELB][i][j]*TO_BLOCKS;
747 	SDL_BlitSurface (to_blocks, &ToGameBlocks[block], ne_screen, &dst);
748       }
749 
750   /* Show the violett playground */
751   for (i = 0; i < NUM_LAYERS - 1; i++)
752     for (j = 0; j < NUM_LINES; j++)
753       {
754 	Set_Rect (dst,
755 		  xoffs + PlaygroundStart[VIOLETT].x +(NUM_LAYERS-i-2)*TO_ElementRect.w,
756 		  yoffs + PlaygroundStart[VIOLETT].y + j * TO_ElementRect.h, 0, 0);
757 	block = ToPlayground[VIOLETT][i][j]+
758 	  (NUM_PHASES+ActivationMap[VIOLETT][i][j])*TO_BLOCKS;
759 	SDL_BlitSurface (to_blocks, &ToGameBlocks[block],ne_screen, &dst);
760       }
761 
762   /* Show the capsules left for each player */
763   for (player = 0; player < 2; player++)
764     {
765       if (player == YOU)
766 	color = YourColor;
767       else
768 	color = OpponentColor;
769 
770       Set_Rect (dst, xoffs + CurCapsuleStart[color].x,
771 		yoffs + CurCapsuleStart[color].y + CapsuleCurRow[color] * TO_CapsuleRect.h,
772 		0,0);
773       if (NumCapsules[player])
774 	SDL_BlitSurface (to_blocks, &CapsuleBlocks[color], ne_screen, &dst);
775 
776 
777       for (i = 0; i < NumCapsules[player]-1; i++)
778 	{
779 	  Set_Rect (dst, xoffs + LeftCapsulesStart[color].x,
780 		    yoffs + LeftCapsulesStart[color].y + i*TO_CapsuleRect.h, 0, 0);
781 	  SDL_BlitSurface (to_blocks, &CapsuleBlocks[color],
782 			   ne_screen, &dst);
783 	} /* for capsules */
784     } /* for player */
785 
786   SDL_Flip (ne_screen);
787 
788   return;
789 
790 }				/* ShowPlayground */
791 
792 
793 /*-----------------------------------------------------------------
794  * @Desc: Clears Playground (and ActivationMap) to default start-values
795  * @Ret:  void
796  *
797  *-----------------------------------------------------------------*/
798 void
ClearPlayground(void)799 ClearPlayground (void)
800 {
801   int color, layer, row;
802 
803   for (color = GELB; color < TO_COLORS; color++)
804     for (layer = 0; layer < NUM_LAYERS; layer++)
805       for (row = 0; row < NUM_LINES; row++)
806 	{
807 	  ActivationMap[color][layer][row] = INACTIVE;
808 	  if (layer < TO_COLORS - 1)
809 	    ToPlayground[color][layer][row] = KABEL;
810 	  else
811 	    ToPlayground[color][layer][row] = INACTIVE;
812 	}
813 
814   for (row = 0; row < NUM_LINES; row++)
815     DisplayColumn[row] = row % 2;
816 
817 }				/* ClearPlayground */
818 
819 
820 /*-----------------------------------------------------------------
821  * @Desc: generate a random Playground
822  *
823  * @Ret: void
824  *
825  *-----------------------------------------------------------------*/
826 void
InventPlayground(void)827 InventPlayground (void)
828 {
829   int anElement;
830   int newElement;
831   int row, layer;
832   int color = GELB;
833 
834   /* first clear the playground: we depend on this !! */
835   ClearPlayground ();
836 
837   for (color = GELB; color < TO_COLORS; color++)
838     {
839       for (layer = 1; layer < NUM_LAYERS - 1; layer++)
840 	{
841 	  for (row = 0; row < NUM_LINES; row++)
842 	    {
843 	      if (ToPlayground[color][layer][row] != KABEL)
844 		continue;
845 
846 	      newElement = MyRandom (TO_ELEMENTS);
847 	      if (MyRandom (MAX_PROB) > ElementProb[newElement])
848 		{
849 		  row--;
850 		  continue;
851 		}
852 
853 	      switch (newElement)
854 		{
855 		case EL_KABEL:	/* has not to be set any more */
856 		  anElement = ToPlayground[color][layer - 1][row];
857 		  if (BlockClass[anElement] == NON_CONNECTOR)
858 		    ToPlayground[color][layer][row] = LEER;
859 		  break;
860 
861 		case EL_KABELENDE:
862 		  anElement = ToPlayground[color][layer - 1][row];
863 		  if (BlockClass[anElement] == NON_CONNECTOR)
864 		    ToPlayground[color][layer][row] = LEER;
865 		  else
866 		    ToPlayground[color][layer][row] = KABELENDE;
867 		  break;
868 
869 		case EL_VERSTAERKER:
870 		  anElement = ToPlayground[color][layer - 1][row];
871 		  if (BlockClass[anElement] == NON_CONNECTOR)
872 		    ToPlayground[color][layer][row] = LEER;
873 		  else
874 		    ToPlayground[color][layer][row] = VERSTAERKER;
875 		  break;
876 
877 		case EL_FARBTAUSCHER:
878 		  if (layer != 2)
879 		    {		/* only existing on layer 2 */
880 		      row--;
881 		      continue;
882 		    }
883 
884 		  anElement = ToPlayground[color][layer - 1][row];
885 		  if (BlockClass[anElement] == NON_CONNECTOR)
886 		    ToPlayground[color][layer][row] = LEER;
887 		  else
888 		    ToPlayground[color][layer][row] = FARBTAUSCHER;
889 		  break;
890 
891 		case EL_VERZWEIGUNG:
892 		  if (row > NUM_LINES - 3)
893 		    {
894 		      /* try again */
895 		      row--;
896 		      break;
897 		    }
898 
899 		  anElement = ToPlayground[color][layer - 1][row + 1];
900 		  if (BlockClass[anElement] == NON_CONNECTOR)
901 		    {
902 		      /* try again */
903 		      row--;
904 		      break;
905 		    }
906 
907 		  /* dont destroy verzweigungen in prev. layer */
908 		  anElement = ToPlayground[color][layer - 1][row];
909 		  if (anElement == VERZWEIGUNG_O
910 		      || anElement == VERZWEIGUNG_U)
911 		    {
912 		      row--;
913 		      break;
914 		    }
915 		  anElement = ToPlayground[color][layer - 1][row + 2];
916 		  if (anElement == VERZWEIGUNG_O
917 		      || anElement == VERZWEIGUNG_U)
918 		    {
919 		      row--;
920 		      break;
921 		    }
922 
923 		  /* cut off kabels in last layer, if any */
924 		  anElement = ToPlayground[color][layer - 1][row];
925 		  if (BlockClass[anElement] == CONNECTOR)
926 		    ToPlayground[color][layer - 1][row] = KABELENDE;
927 
928 		  anElement = ToPlayground[color][layer - 1][row + 2];
929 		  if (BlockClass[anElement] == CONNECTOR)
930 		    ToPlayground[color][layer - 1][row + 2] = KABELENDE;
931 
932 		  /* set the verzweigung itself */
933 		  ToPlayground[color][layer][row] = VERZWEIGUNG_O;
934 		  ToPlayground[color][layer][row + 1] = VERZWEIGUNG_M;
935 		  ToPlayground[color][layer][row + 2] = VERZWEIGUNG_U;
936 
937 		  row += 2;
938 		  break;
939 
940 		case EL_GATTER:
941 		  if (row > NUM_LINES - 3)
942 		    {
943 		      /* try again */
944 		      row--;
945 		      break;
946 		    }
947 
948 		  anElement = ToPlayground[color][layer - 1][row];
949 		  if (BlockClass[anElement] == NON_CONNECTOR)
950 		    {
951 		      /* try again */
952 		      row--;
953 		      break;
954 		    }
955 		  anElement = ToPlayground[color][layer - 1][row + 2];
956 		  if (BlockClass[anElement] == NON_CONNECTOR)
957 		    {
958 		      /* try again */
959 		      row--;
960 		      break;
961 		    }
962 
963 
964 		  /* cut off kabels in last layer, if any */
965 		  anElement = ToPlayground[color][layer - 1][row + 1];
966 		  if (BlockClass[anElement] == CONNECTOR)
967 		    ToPlayground[color][layer - 1][row + 1] = KABELENDE;
968 
969 		  /* set the GATTER itself */
970 		  ToPlayground[color][layer][row] = GATTER_O;
971 		  ToPlayground[color][layer][row + 1] = GATTER_M;
972 		  ToPlayground[color][layer][row + 2] = GATTER_U;
973 
974 		  row += 2;
975 		  break;
976 
977 		default:
978 		  row--;
979 		  break;
980 
981 		}		/* switch NewElement */
982 
983 	    }			/* for row */
984 
985 	}			/* for layer */
986 
987     }				/* for color */
988 
989 }				/* InventPlayground */
990 
991 /*-----------------------------------------------------------------
992  * @Desc: process the playground following its intrinsic logic
993  *
994  * @Ret: void
995  *
996  *-----------------------------------------------------------------*/
997 void
ProcessPlayground(void)998 ProcessPlayground (void)
999 {
1000   int color, layer, row;
1001   int TurnActive = FALSE;
1002 
1003   for (color = GELB; color < TO_COLORS; color++)
1004     {
1005       for (layer = 1; layer < NUM_LAYERS; layer++)
1006 	{
1007 	  for (row = 0; row < NUM_LINES; row++)
1008 	    {
1009 	      if (layer == NUM_LAYERS - 1)
1010 		{
1011 		  if (IsActive (color, row))
1012 		    ActivationMap[color][layer][row] = ACTIVE1;
1013 		  else
1014 		    ActivationMap[color][layer][row] = INACTIVE;
1015 
1016 		  continue;
1017 		}		/* if last layer */
1018 
1019 	      TurnActive = FALSE;
1020 
1021 	      switch (ToPlayground[color][layer][row])
1022 		{
1023 		case FARBTAUSCHER:
1024 		case VERZWEIGUNG_M:
1025 		case GATTER_O:
1026 		case GATTER_U:
1027 		case KABEL:
1028 		  if (ActivationMap[color][layer - 1][row] >= ACTIVE1)
1029 		    TurnActive = TRUE;
1030 		  break;
1031 
1032 		case VERSTAERKER:
1033 		  if (ActivationMap[color][layer - 1][row] >= ACTIVE1)
1034 		    TurnActive = TRUE;
1035 
1036 		  /* Verstaerker halten sich aber auch selbst aktiv !! */
1037 		  if (ActivationMap[color][layer][row] >= ACTIVE1)
1038 		    TurnActive = TRUE;
1039 
1040 		  break;
1041 
1042 		case KABELENDE:
1043 		  break;
1044 
1045 		case VERZWEIGUNG_O:
1046 		  if (ActivationMap[color][layer][row + 1] >= ACTIVE1)
1047 		    TurnActive = TRUE;
1048 		  break;
1049 
1050 		case VERZWEIGUNG_U:
1051 		  if (ActivationMap[color][layer][row - 1] >= ACTIVE1)
1052 		    TurnActive = TRUE;
1053 		  break;
1054 
1055 		case GATTER_M:
1056 		  if ((ActivationMap[color][layer][row - 1] >= ACTIVE1)
1057 		      && (ActivationMap[color][layer][row + 1] >= ACTIVE1))
1058 		    TurnActive = TRUE;
1059 
1060 		  break;
1061 
1062 		default:
1063 		  break;
1064 		}		/* switch */
1065 
1066 	      if (TurnActive)
1067 		{
1068 		  if (ActivationMap[color][layer][row] == INACTIVE)
1069 		    ActivationMap[color][layer][row] = ACTIVE1;
1070 		  TurnActive = FALSE;
1071 		}
1072 	      else
1073 		ActivationMap[color][layer][row] = INACTIVE;
1074 
1075 
1076 	    }			/* for row */
1077 
1078 	}			/* for layer */
1079 
1080     }				/* for color */
1081 
1082   return;
1083 }				/* ProcessPlayground */
1084 
1085 
1086 
1087 /*@Function============================================================
1088 @Desc:  ProcessDisplayColumn(): setzt die Korrekten Werte in der Display-
1089         Saeule. Blinkende LEDs werden ebenfalls hier realisiert
1090 
1091 @Ret: void
1092 @Int:
1093 * $Function----------------------------------------------------------*/
1094 void
ProcessDisplayColumn(void)1095 ProcessDisplayColumn (void)
1096 {
1097   static int CLayer = 3;	/* the connection-layer to the Column */
1098   static int flicker_color = 0;
1099   int row;
1100   int GelbCounter, ViolettCounter;
1101 
1102   flicker_color = !flicker_color;
1103 
1104   for (row = 0; row < NUM_LINES; row++)
1105     {
1106       /* eindeutig gelb */
1107       if ((ActivationMap[GELB][CLayer][row] >= ACTIVE1) &&
1108 	  (ActivationMap[VIOLETT][CLayer][row] == INACTIVE))
1109 	{
1110 	  /* Farbtauscher ??? */
1111 	  if (ToPlayground[GELB][CLayer - 1][row] == FARBTAUSCHER)
1112 	    DisplayColumn[row] = VIOLETT;
1113 	  else
1114 	    DisplayColumn[row] = GELB;
1115 	  continue;
1116 	}
1117 
1118       /* eindeutig violett */
1119       if ((ActivationMap[GELB][CLayer][row] == INACTIVE) &&
1120 	  (ActivationMap[VIOLETT][CLayer][row] >= ACTIVE1))
1121 	{
1122 	  /* Farbtauscher ??? */
1123 	  if (ToPlayground[VIOLETT][CLayer - 1][row] == FARBTAUSCHER)
1124 	    DisplayColumn[row] = GELB;
1125 	  else
1126 	    DisplayColumn[row] = VIOLETT;
1127 
1128 	  continue;
1129 	}
1130 
1131       /* unentschieden: Flimmern */
1132       if ((ActivationMap[GELB][CLayer][row] >= ACTIVE1) &&
1133 	  (ActivationMap[VIOLETT][CLayer][row] >= ACTIVE1))
1134 	{
1135 	  /* Farbtauscher - Faelle */
1136 	  if ((ToPlayground[GELB][CLayer - 1][row] == FARBTAUSCHER) &&
1137 	      (ToPlayground[VIOLETT][CLayer - 1][row] != FARBTAUSCHER))
1138 	    DisplayColumn[row] = VIOLETT;
1139 	  else if ((ToPlayground[GELB][CLayer - 1][row] != FARBTAUSCHER) &&
1140 		   (ToPlayground[VIOLETT][CLayer - 1][row] == FARBTAUSCHER))
1141 	    DisplayColumn[row] = GELB;
1142 	  else
1143 	    {
1144 	      if (flicker_color == 0)
1145 		DisplayColumn[row] = GELB;
1146 	      else
1147 		DisplayColumn[row] = VIOLETT;
1148 	    }			/* if - else if - else */
1149 
1150 	}			/* if unentschieden */
1151 
1152     }				/* for */
1153 
1154   /* Win Color beurteilen */
1155   GelbCounter = 0;
1156   ViolettCounter = 0;
1157   for (row = 0; row < NUM_LINES; row++)
1158     if (DisplayColumn[row] == GELB)
1159       GelbCounter++;
1160     else
1161       ViolettCounter++;
1162 
1163   if (ViolettCounter < GelbCounter)
1164     LeaderColor = GELB;
1165   else if (ViolettCounter > GelbCounter)
1166     LeaderColor = VIOLETT;
1167   else
1168     LeaderColor = REMIS;
1169 
1170   //--------------------
1171   // In Freedroid, the resistance a droid against the influencers control should
1172   // depend on the details of the final takeover score.  Therefore we set this
1173   // resistance factor variable here.
1174   //
1175   // RP: yes, but as this is now a purely "classic" release, such extensions are
1176   // deactivated...
1177   //  Me.Current_Victim_Resistance_Factor = 0.2 * ( (float) 12 - abs( ViolettCounter- GelbCounter ) );
1178 
1179   return;
1180 }; // ProcessDisplayColumn
1181 
1182 /*@Function============================================================
1183 @Desc: ProcessCapsules():	does the countdown of the capsules and
1184 									kills them if too old
1185 
1186 @Ret: void
1187 @Int:
1188 * $Function----------------------------------------------------------*/
1189 void
ProcessCapsules(void)1190 ProcessCapsules (void)
1191 {
1192   int row;
1193   int color;
1194 
1195   for (color = GELB; color <= VIOLETT; color++)
1196     for (row = 0; row < NUM_LINES; row++)
1197       {
1198 	if (CapsuleCountdown[color][0][row] > 0)
1199 	  CapsuleCountdown[color][0][row]--;
1200 
1201 	if (CapsuleCountdown[color][0][row] == 0)
1202 	  {
1203 	    CapsuleCountdown[color][0][row] = -1;
1204 	    ActivationMap[color][0][row] = INACTIVE;
1205 	    ToPlayground[color][0][row] = KABEL;
1206 	  }
1207 
1208       } /* for row */
1209 
1210 }   /* ProcessCapsules() */
1211 
1212 
1213 /*@Function============================================================
1214 @Desc: IsInactive(color, row): tells, wether a Column-connection
1215 						is active or not
1216 
1217 @Ret: TRUE/FALSE
1218 @Int:
1219 * $Function----------------------------------------------------------*/
1220 int
IsActive(int color,int row)1221 IsActive (int color, int row)
1222 {
1223   int CLayer = 3;		/* the connective Layer */
1224   int TestElement = ToPlayground[color][CLayer - 1][row];
1225 
1226   if ((ActivationMap[color][CLayer-1][row] >= ACTIVE1) &&
1227       (BlockClass[TestElement] == CONNECTOR))
1228     return TRUE;
1229   else
1230     return FALSE;
1231 }				/* IsActive */
1232 
1233 /*-----------------------------------------------------------------
1234  *
1235  * Animate the active cables: this is done by cycling over
1236  * the active phases ACTIVE1-ACTIVE3, which are represented by
1237  * different pictures in the playground
1238  *
1239  *-----------------------------------------------------------------*/
1240 void
AnimateCurrents(void)1241 AnimateCurrents (void)
1242 {
1243   int color, layer, row;
1244 
1245   for (color = GELB; color <= VIOLETT; color ++)
1246     for (layer = 0; layer < NUM_LAYERS; layer ++)
1247       for (row = 0; row < NUM_LINES; row ++)
1248 	if (ActivationMap[color][layer][row] >= ACTIVE1)
1249 	  {
1250 	    ActivationMap[color][layer][row] ++;
1251 	    if (ActivationMap[color][layer][row] == NUM_PHASES)
1252 	      ActivationMap[color][layer][row] = ACTIVE1;
1253 	  }
1254 
1255   return;
1256 }
1257 
1258 
1259 #undef _takeover_c
1260