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