Bug Summary

File:src/takeover.c
Location:line 743, column 5
Description:Value stored to 'row' is never read

Annotated Source Code

1/*
2 *
3 * Copyright (c) 2004-2010 Arthur Huillet
4 * Copyright (c) 1994, 2002, 2003 Johannes Prix
5 * Copyright (c) 1994, 2002 Reinhard Prix
6 *
7 *
8 * This file is part of Freedroid
9 *
10 * Freedroid is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * Freedroid is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with Freedroid; see the file COPYING. If not, write to the
22 * Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
23 * MA 02111-1307 USA
24 *
25 */
26/**
27 * This file does everything that has to do with the takeover game from
28 * the original paradroid game.
29 */
30
31#define _takeover_c
32
33#include "system.h"
34
35#include "defs.h"
36#include "struct.h"
37#include "global.h"
38#include "proto.h"
39#include "takeover.h"
40#include "map.h"
41#include "widgets/widgets.h"
42
43Uint32 cur_time; // current time in ms
44
45// Takeover images
46static struct image FillBlocks[NUM_FILL_BLOCKS3];
47static struct image CapsuleBlocks[NUM_CAPS_BLOCKS3];
48static struct image ToGameBlocks[NUM_TO_BLOCKS2*5*11];
49static struct image ToGroundBlocks[NUM_GROUND_BLOCKS6];
50static struct image ToColumnBlock;
51static struct image ToLeaderBlock;
52
53//--------------------
54// Class seperation of the blocks
55//
56int BlockClass[TO_BLOCKS11] = {
57 CONNECTOR0, // cable
58 NON_CONNECTOR1, // end of cable
59 CONNECTOR0, // re-enforcer
60 CONNECTOR0, // color-change
61 CONNECTOR0, // bridge above
62 NON_CONNECTOR1, // bridge middle
63 CONNECTOR0, // bridge below
64 NON_CONNECTOR1, // uniter above
65 CONNECTOR0, // uniter middle
66 NON_CONNECTOR1, // uniter below
67 NON_CONNECTOR1 // empty
68};
69
70//--------------------
71// Probability of the various elements
72//
73#define MAX_PROB100 100
74int ElementProb[TO_ELEMENTS6] = {
75 100, // EL_CABLE
76 2, // EL_CABLE_END
77 5, // EL_AMPLIFIER
78 5, // EL_COLOR_EXCHANGER: only on last layer
79 5, // EL_SEPARATOR
80 5 // EL_GATE
81};
82
83int max_opponent_capsules;
84int NumCapsules[TO_COLORS2] = {
85 0, 0
86};
87
88point LeftCapsulesStart[TO_COLORS2] = {
89 {YELLOW_LEFT_CAPSULES_X4, YELLOW_LEFT_CAPSULES_Y2*27},
90 {PURPLE_LEFT_CAPSULES_X2*255 + 2*30 -10, PURPLE_LEFT_CAPSULES_Y2*27}
91};
92
93point CurCapsuleStart[TO_COLORS2] = {
94 {YELLOW_CUR_CAPSULE_X2*26, YELLOW_CUR_CAPSULE_Y2*19},
95 {PURPLE_CUR_CAPSULE_X2*255, PURPLE_CUR_CAPSULE_Y2*19}
96};
97
98point PlaygroundStart[TO_COLORS2] = {
99 {YELLOW_PLAYGROUND_X2*33, YELLOW_PLAYGROUND_Y2*26},
100 {PURPLE_PLAYGROUND_X2*159, PURPLE_PLAYGROUND_Y2*26}
101};
102
103point DroidStart[TO_COLORS2] = {
104 {YELLOW_DROID_X2*40, YELLOW_DROID_Y0},
105 {PURPLE_DROID_X2*220, PURPLE_DROID_Y0}
106};
107
108int CapsuleCurRow[TO_COLORS2] = { 0, 0 };
109
110int LeaderColor = YELLOW; /* momentary leading color */
111int LeaderCapsuleCount = 6; /* capsule count of currently leading color */
112int YourColor = YELLOW;
113int OpponentColor = PURPLE;
114int OpponentType; /* The droid-type of your opponent */
115enemy *cdroid;
116
117/* the display column */
118int DisplayColumn[NUM_LINES12] = {
119 YELLOW, PURPLE, YELLOW, PURPLE, YELLOW, PURPLE, YELLOW, PURPLE, YELLOW, PURPLE,
120 YELLOW, PURPLE
121};
122
123SDL_Color to_bg_color = { 199, 199, 199 };
124
125playground_t ToPlayground;
126playground_t ActivationMap;
127playground_t CapsuleCountdown;
128
129void EvaluatePlayground(void);
130float EvaluatePosition(const int color, const int row, const int layer, const int endgame);
131float EvaluateCenterPosition(const int color, const int row, const int layer, const int endgame);
132void AdvancedEnemyTakeoverMovements(const int countdown);
133
134static void ShowPlayground(enemy *target);
135
136static void display_takeover_help()
137{
138 PlayATitleFile("TakeoverInstructions.lua");
139}
140
141/**
142 * Display the picture of a droid
143 */
144static void show_droid_picture(int PosX, int PosY, int type)
145{
146 char filename[5000];
147 static char LastImageSeriesPrefix[1000] = "NONE_AT_ALL";
148#define NUMBER_OF_IMAGES_IN_DROID_PORTRAIT_ROTATION32 32
149 static struct image droid_images[NUMBER_OF_IMAGES_IN_DROID_PORTRAIT_ROTATION32];
150 int RotationIndex;
151
152 if (!strcmp(Droidmap[type].droid_portrait_rotation_series_prefix, "NONE_AVAILABLE_YET")__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(Droidmap[type].droid_portrait_rotation_series_prefix) &&
__builtin_constant_p ("NONE_AVAILABLE_YET") && (__s1_len
= strlen (Droidmap[type].droid_portrait_rotation_series_prefix
), __s2_len = strlen ("NONE_AVAILABLE_YET"), (!((size_t)(const
void *)((Droidmap[type].droid_portrait_rotation_series_prefix
) + 1) - (size_t)(const void *)(Droidmap[type].droid_portrait_rotation_series_prefix
) == 1) || __s1_len >= 4) && (!((size_t)(const void
*)(("NONE_AVAILABLE_YET") + 1) - (size_t)(const void *)("NONE_AVAILABLE_YET"
) == 1) || __s2_len >= 4)) ? __builtin_strcmp (Droidmap[type
].droid_portrait_rotation_series_prefix, "NONE_AVAILABLE_YET"
) : (__builtin_constant_p (Droidmap[type].droid_portrait_rotation_series_prefix
) && ((size_t)(const void *)((Droidmap[type].droid_portrait_rotation_series_prefix
) + 1) - (size_t)(const void *)(Droidmap[type].droid_portrait_rotation_series_prefix
) == 1) && (__s1_len = strlen (Droidmap[type].droid_portrait_rotation_series_prefix
), __s1_len < 4) ? (__builtin_constant_p ("NONE_AVAILABLE_YET"
) && ((size_t)(const void *)(("NONE_AVAILABLE_YET") +
1) - (size_t)(const void *)("NONE_AVAILABLE_YET") == 1) ? __builtin_strcmp
(Droidmap[type].droid_portrait_rotation_series_prefix, "NONE_AVAILABLE_YET"
) : (__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) ("NONE_AVAILABLE_YET"); int __result =
(((const unsigned char *) (const char *) (Droidmap[type].droid_portrait_rotation_series_prefix
))[0] - __s2[0]); if (__s1_len > 0 && __result == 0
) { __result = (((const unsigned char *) (const char *) (Droidmap
[type].droid_portrait_rotation_series_prefix))[1] - __s2[1]);
if (__s1_len > 1 && __result == 0) { __result = (
((const unsigned char *) (const char *) (Droidmap[type].droid_portrait_rotation_series_prefix
))[2] - __s2[2]); if (__s1_len > 2 && __result == 0
) __result = (((const unsigned char *) (const char *) (Droidmap
[type].droid_portrait_rotation_series_prefix))[3] - __s2[3]);
} } __result; }))) : (__builtin_constant_p ("NONE_AVAILABLE_YET"
) && ((size_t)(const void *)(("NONE_AVAILABLE_YET") +
1) - (size_t)(const void *)("NONE_AVAILABLE_YET") == 1) &&
(__s2_len = strlen ("NONE_AVAILABLE_YET"), __s2_len < 4) ?
(__builtin_constant_p (Droidmap[type].droid_portrait_rotation_series_prefix
) && ((size_t)(const void *)((Droidmap[type].droid_portrait_rotation_series_prefix
) + 1) - (size_t)(const void *)(Droidmap[type].droid_portrait_rotation_series_prefix
) == 1) ? __builtin_strcmp (Droidmap[type].droid_portrait_rotation_series_prefix
, "NONE_AVAILABLE_YET") : (- (__extension__ ({ const unsigned
char *__s2 = (const unsigned char *) (const char *) (Droidmap
[type].droid_portrait_rotation_series_prefix); int __result =
(((const unsigned char *) (const char *) ("NONE_AVAILABLE_YET"
))[0] - __s2[0]); if (__s2_len > 0 && __result == 0
) { __result = (((const unsigned char *) (const char *) ("NONE_AVAILABLE_YET"
))[1] - __s2[1]); if (__s2_len > 1 && __result == 0
) { __result = (((const unsigned char *) (const char *) ("NONE_AVAILABLE_YET"
))[2] - __s2[2]); if (__s2_len > 2 && __result == 0
) __result = (((const unsigned char *) (const char *) ("NONE_AVAILABLE_YET"
))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (Droidmap
[type].droid_portrait_rotation_series_prefix, "NONE_AVAILABLE_YET"
)))); })
)
153 return;
154
155 // Maybe we have to reload the whole image series
156 //
157 if (strcmp(LastImageSeriesPrefix, Droidmap[type].droid_portrait_rotation_series_prefix)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(LastImageSeriesPrefix) && __builtin_constant_p (Droidmap
[type].droid_portrait_rotation_series_prefix) && (__s1_len
= strlen (LastImageSeriesPrefix), __s2_len = strlen (Droidmap
[type].droid_portrait_rotation_series_prefix), (!((size_t)(const
void *)((LastImageSeriesPrefix) + 1) - (size_t)(const void *
)(LastImageSeriesPrefix) == 1) || __s1_len >= 4) &&
(!((size_t)(const void *)((Droidmap[type].droid_portrait_rotation_series_prefix
) + 1) - (size_t)(const void *)(Droidmap[type].droid_portrait_rotation_series_prefix
) == 1) || __s2_len >= 4)) ? __builtin_strcmp (LastImageSeriesPrefix
, Droidmap[type].droid_portrait_rotation_series_prefix) : (__builtin_constant_p
(LastImageSeriesPrefix) && ((size_t)(const void *)((
LastImageSeriesPrefix) + 1) - (size_t)(const void *)(LastImageSeriesPrefix
) == 1) && (__s1_len = strlen (LastImageSeriesPrefix)
, __s1_len < 4) ? (__builtin_constant_p (Droidmap[type].droid_portrait_rotation_series_prefix
) && ((size_t)(const void *)((Droidmap[type].droid_portrait_rotation_series_prefix
) + 1) - (size_t)(const void *)(Droidmap[type].droid_portrait_rotation_series_prefix
) == 1) ? __builtin_strcmp (LastImageSeriesPrefix, Droidmap[type
].droid_portrait_rotation_series_prefix) : (__extension__ ({ const
unsigned char *__s2 = (const unsigned char *) (const char *)
(Droidmap[type].droid_portrait_rotation_series_prefix); int __result
= (((const unsigned char *) (const char *) (LastImageSeriesPrefix
))[0] - __s2[0]); if (__s1_len > 0 && __result == 0
) { __result = (((const unsigned char *) (const char *) (LastImageSeriesPrefix
))[1] - __s2[1]); if (__s1_len > 1 && __result == 0
) { __result = (((const unsigned char *) (const char *) (LastImageSeriesPrefix
))[2] - __s2[2]); if (__s1_len > 2 && __result == 0
) __result = (((const unsigned char *) (const char *) (LastImageSeriesPrefix
))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p (
Droidmap[type].droid_portrait_rotation_series_prefix) &&
((size_t)(const void *)((Droidmap[type].droid_portrait_rotation_series_prefix
) + 1) - (size_t)(const void *)(Droidmap[type].droid_portrait_rotation_series_prefix
) == 1) && (__s2_len = strlen (Droidmap[type].droid_portrait_rotation_series_prefix
), __s2_len < 4) ? (__builtin_constant_p (LastImageSeriesPrefix
) && ((size_t)(const void *)((LastImageSeriesPrefix) +
1) - (size_t)(const void *)(LastImageSeriesPrefix) == 1) ? __builtin_strcmp
(LastImageSeriesPrefix, Droidmap[type].droid_portrait_rotation_series_prefix
) : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) (LastImageSeriesPrefix); int __result
= (((const unsigned char *) (const char *) (Droidmap[type].droid_portrait_rotation_series_prefix
))[0] - __s2[0]); if (__s2_len > 0 && __result == 0
) { __result = (((const unsigned char *) (const char *) (Droidmap
[type].droid_portrait_rotation_series_prefix))[1] - __s2[1]);
if (__s2_len > 1 && __result == 0) { __result = (
((const unsigned char *) (const char *) (Droidmap[type].droid_portrait_rotation_series_prefix
))[2] - __s2[2]); if (__s2_len > 2 && __result == 0
) __result = (((const unsigned char *) (const char *) (Droidmap
[type].droid_portrait_rotation_series_prefix))[3] - __s2[3]);
} } __result; })))) : __builtin_strcmp (LastImageSeriesPrefix
, Droidmap[type].droid_portrait_rotation_series_prefix)))); }
)
) {
158 int i;
159 for (i = 0; i < NUMBER_OF_IMAGES_IN_DROID_PORTRAIT_ROTATION32; i++) {
160 delete_image(&droid_images[i]);
161
162 sprintf(filename, "droids/%s/portrait_%04d.jpg", Droidmap[type].droid_portrait_rotation_series_prefix, i + 1);
163
164 load_image(&droid_images[i], filename, FALSE(0));
165 }
166
167 strcpy(LastImageSeriesPrefix, Droidmap[type].droid_portrait_rotation_series_prefix);
168 }
169
170 RotationIndex = (SDL_GetTicks() / 50);
171
172 RotationIndex =
173 RotationIndex - (RotationIndex / NUMBER_OF_IMAGES_IN_DROID_PORTRAIT_ROTATION32) * NUMBER_OF_IMAGES_IN_DROID_PORTRAIT_ROTATION32;
174
175 // Compute the maximum uniform scale to apply to the bot image so that it fills
176 // the droid portrait image, and center the image.
177 struct image *img = &droid_images[RotationIndex];
178 float scale = min((float)Droid_Image_Window.w / (float)img->w, (float)Droid_Image_Window.h / (float)img->h)(((float)Droid_Image_Window.w / (float)img->w) > ((float
)Droid_Image_Window.h / (float)img->h) ? ((float)Droid_Image_Window
.h / (float)img->h) : ((float)Droid_Image_Window.w / (float
)img->w) )
;
179 moderately_finepoint pos;
180 pos.x = (float)PosX + ((float)Droid_Image_Window.w - (float)img->w * scale) / 2.0;
181 pos.y = (float)PosY + ((float)Droid_Image_Window.h - (float)img->h * scale) / 2.0;
182 display_image_on_screen(img, pos.x, pos.y, IMAGE_SCALE_TRANSFO(scale)set_image_transformation(scale, scale, 1.0, 1.0, 1.0, 1.0, 0));
183}
184
185/**
186 * Display infopage page of droidtype.
187 */
188static void show_droid_info(int droidtype)
189{
190 SDL_Rect clip;
191
192 SDL_SetClipRect(Screen, NULL((void*)0));
193
194 // Show background
195 blit_background("console_bg1.jpg");
196 blit_background("takeover_browser.png");
197
198 // Show droid portrait
199 show_droid_picture(UNIVERSAL_COORD_W(45)(int)((float)(45) * ((float)(GameConfig . screen_width) / 640.0
))
, UNIVERSAL_COORD_H(213)(int)((float)(213) * ((float)(GameConfig . screen_height) / 480.0
))
, droidtype);
200
201 // Show the droid name
202 SetCurrentFont(Menu_BFont);
203 clip.x = UNIVERSAL_COORD_W(330)(int)((float)(330) * ((float)(GameConfig . screen_width) / 640.0
))
;
204 clip.y = UNIVERSAL_COORD_H(57)(int)((float)(57) * ((float)(GameConfig . screen_height) / 480.0
))
;
205 clip.w = UNIVERSAL_COORD_W(200)(int)((float)(200) * ((float)(GameConfig . screen_width) / 640.0
))
;
206 clip.h = UNIVERSAL_COORD_H(30)(int)((float)(30) * ((float)(GameConfig . screen_height) / 480.0
))
;
207 display_text_using_line_height(D_(Droidmap[droidtype].default_short_description)(Droidmap[droidtype].default_short_description[0]!='\0'?dcgettext
("freedroidrpg-data", Droidmap[droidtype].default_short_description
, 5):"")
, clip.x, clip.y, &clip, 1.0);
208}
209
210/**
211 * Initialize text widget with a description of the specified droidtype.
212 */
213static void init_droid_description(struct widget_text *w, int droidtype)
214{
215 const char *item_name;
216 int weapon_type;
217
218 autostr_append(w->text, _("Unit Type %s\n")("Unit Type %s\n"[0]!='\0'?dcgettext (((void*)0), "Unit Type %s\n"
, 5):"")
, Droidmap[droidtype].droidname);
219 autostr_append(w->text, _("Entry : %d\n")("Entry : %d\n"[0]!='\0'?dcgettext (((void*)0), "Entry : %d\n"
, 5):"")
, droidtype + 1);
220
221 if ((weapon_type = Droidmap[droidtype].weapon_item.type) >= 0) // make sure item != -1
222 item_name = D_(item_specs_get_name(weapon_type))(item_specs_get_name(weapon_type)[0]!='\0'?dcgettext ("freedroidrpg-data"
, item_specs_get_name(weapon_type), 5):"")
; // does not segfault
223 else
224 item_name = _("none")("none"[0]!='\0'?dcgettext (((void*)0), "none", 5):"");
225
226 autostr_append(w->text, _("\nArmament : %s\n")("\nArmament : %s\n"[0]!='\0'?dcgettext (((void*)0), "\nArmament : %s\n"
, 5):"")
, item_name);
227 autostr_append(w->text, _("\nCores : %d\n")("\nCores : %d\n"[0]!='\0'?dcgettext (((void*)0), "\nCores : %d\n"
, 5):"")
, 2 + Droidmap[droidtype].class);
228
229
230 if (Me.TakeoverSuccesses[droidtype]+Me.TakeoverFailures[droidtype]) {
231 int success_ratio =
232 ((100*Me.TakeoverSuccesses[droidtype])/
233 (Me.TakeoverSuccesses[droidtype]+Me.TakeoverFailures[droidtype]));
234
235 autostr_append(w->text, _("\nTakeover Success : %2d%%\n")("\nTakeover Success : %2d%%\n"[0]!='\0'?dcgettext (((void*)0
), "\nTakeover Success : %2d%%\n", 5):"")
, success_ratio);
236 }
237
238 autostr_append(w->text, _("\nNotes: %s\n")("\nNotes: %s\n"[0]!='\0'?dcgettext (((void*)0), "\nNotes: %s\n"
, 5):"")
, D_(Droidmap[droidtype].notes)(Droidmap[droidtype].notes[0]!='\0'?dcgettext ("freedroidrpg-data"
, Droidmap[droidtype].notes, 5):"")
);
239}
240
241/**
242 * This function does the countdown where you still can changes your
243 * color.
244 */
245static void ChooseColor(enemy *target)
246{
247 int countdown = 100; // duration in 1/10 seconds given for color choosing
248 int ColorChosen = FALSE(0);
249 char count_text[80];
250 SDL_Event event;
251
252 Uint32 prev_count_tick, count_tick_len;
253
254 count_tick_len = 100; // countdown in 1/10 second steps
255
256 prev_count_tick = SDL_GetTicks();
257
258 while (!ColorChosen) {
259
260 // wait for next countdown tick
261 while (SDL_GetTicks() < prev_count_tick + count_tick_len) ;
262
263 prev_count_tick += count_tick_len; // set for next tick
264
265 while (SDL_PollEvent(&event)) {
266
267 if (event.type == SDL_QUIT) {
268 Terminate(EXIT_SUCCESS0);
269 }
270
271 if (event.type == SDL_MOUSEBUTTONDOWN) {
272 switch (event.button.button) {
273 //(clever?) hack : mouse wheel up and down behave
274 //exactly like LEFT and RIGHT arrow, so we mangle the event
275 case SDL_BUTTON_WHEELUP4:
276 event.type = SDL_KEYDOWN;
277 event.key.keysym.sym = SDLK_LEFT;
278 break;
279 case SDL_BUTTON_WHEELDOWN5:
280 event.type = SDL_KEYDOWN;
281 event.key.keysym.sym = SDLK_RIGHT;
282 break;
283 case SDL_BUTTON_LEFT1:
284 ColorChosen = TRUE(1);
285 break;
286
287 default:
288 break;
289 }
290 }
291
292 /* no else there! (mouse wheel) */
293 if (event.type == SDL_KEYDOWN) {
294 switch (event.key.keysym.sym) {
295 case SDLK_RIGHT:
296 YourColor = PURPLE;
297 OpponentColor = YELLOW;
298 break;
299 case SDLK_LEFT:
300 YourColor = YELLOW;
301 OpponentColor = PURPLE;
302 break;
303 case SDLK_SPACE:
304 ColorChosen = TRUE(1);
305 break;
306 default:
307 break;
308 }
309 }
310
311 }
312
313 countdown--; // Count down
314 sprintf(count_text, _("Color-%d.%d")("Color-%d.%d"[0]!='\0'?dcgettext (((void*)0), "Color-%d.%d",
5):"")
, countdown/10, countdown%10);
315
316 ShowPlayground(target);
317 to_show_banner(count_text, NULL((void*)0));
318 our_SDL_flip_wrapper();
319
320 if (countdown == 0)
321 ColorChosen = TRUE(1);
322
323 } // while(!ColorChosen)
324
325 while (MouseLeftPressed())
326 SDL_Delay(1);
327}; // void ChooseColor ( void )
328
329static void PlayGame(int countdown, enemy *target)
330{
331 char count_text[80];
332 int FinishTakeover = FALSE(0);
333 int row;
334
335 Uint32 prev_count_tick, count_tick_len; /* tick vars for count-down */
336 Uint32 prev_move_tick, move_tick_len; /* tick vars for motion */
337 int wait_move_ticks; /* number of move-ticks to wait before "key-repeat" */
338
339 int up, down, set;
340 int up_counter, down_counter;
341
342 SDL_Event event;
343
344 sprintf(count_text, " "); /* Make sure a value gets assigned to count_text */
345 count_tick_len = 100; /* countdown in 1/10 second steps */
346 move_tick_len = 60; /* allow motion at this tick-speed in ms */
347
348 up = down = set = FALSE(0);
349 up_counter = down_counter = 0;
350
351 wait_move_ticks = 2;
352
353 prev_count_tick = prev_move_tick = SDL_GetTicks(); /* start tick clock */
354
355 while (!FinishTakeover) {
356 cur_time = SDL_GetTicks();
357
358 /*
359 * here we register if there have been key-press events in the
360 * "waiting period" between move-ticks :
361 */
362 up = (up | UpPressed());
363 down = (down | DownPressed());
364 set = set | SpacePressed() | MouseLeftPressed();
365
366 while (SDL_PollEvent(&event)) {
367 if (event.type == SDL_MOUSEBUTTONDOWN) {
368 switch (event.button.button) {
369 case SDL_BUTTON_WHEELUP4:
370 up++;
371 break;
372 case SDL_BUTTON_WHEELDOWN5:
373 down++;
374 break;
375 default:
376 break;
377 }
378 } else if (event.type == SDL_KEYDOWN) {
379 /* allow for a WIN-key that gives immediate victory */
380 event.key.keysym.mod &= ~(KMOD_CAPS | KMOD_NUM | KMOD_MODE); /* We want to ignore "global" modifiers. */
381 if (event.key.keysym.sym == SDLK_w && (event.key.keysym.mod == (KMOD_LCTRL | KMOD_LALT))) {
382 LeaderColor = YourColor; /* simple as that */
383 return; /* leave now, to avoid changing of LeaderColor! */
384 }
385 } else if (event.type == SDL_QUIT) {
386 Terminate(EXIT_SUCCESS0);
387 }
388 }
389
390 if (!up)
391 up_counter = 0; /* reset counters for released keys */
392 if (!down)
393 down_counter = 0;
394
395 if (cur_time > prev_count_tick + count_tick_len) { /* time to count 1 down */
396 prev_count_tick += count_tick_len; /* set for next countdown tick */
397 countdown--;
398 sprintf(count_text, _("Finish-%d.%d")("Finish-%d.%d"[0]!='\0'?dcgettext (((void*)0), "Finish-%d.%d"
, 5):"")
, countdown/10, countdown%10);
399
400 if (countdown == 0)
401 FinishTakeover = TRUE(1);
402
403 AnimateCurrents(); /* do some animation on the active cables */
404
405 }
406
407 /* if (countdown_tick has occurred) */
408 /* time for movement */
409 if (cur_time > prev_move_tick + move_tick_len) {
410 prev_move_tick += move_tick_len; /* set for next motion tick */
411 AdvancedEnemyTakeoverMovements(countdown);
412
413 if (up) {
414 if (!up_counter || (up_counter > wait_move_ticks)) {
415 // Here I have to change some things in order to make
416 // mouse movement work properly with the wheel...
417 //
418 // CapsuleCurRow[YourColor]--;
419 //
420 CapsuleCurRow[YourColor] -= up;
421
422 if (CapsuleCurRow[YourColor] < 1)
423 CapsuleCurRow[YourColor] = NUM_LINES12;
424 }
425 up = FALSE(0);
426 up_counter++;
427 }
428 if (down) {
429 if (!down_counter || (down_counter > wait_move_ticks)) {
430 // Here I have to change some things in order to make
431 // mouse movement work properly with the wheel...
432 //
433 // CapsuleCurRow[YourColor]++;
434 //
435 CapsuleCurRow[YourColor] += down;
436
437 if (CapsuleCurRow[YourColor] > NUM_LINES12)
438 CapsuleCurRow[YourColor] = 1;
439 }
440 down = FALSE(0);
441 down_counter++;
442 }
443
444 if (set && (NumCapsules[YOU] > 0)) {
445 set = FALSE(0);
446 row = CapsuleCurRow[YourColor] - 1;
447 if ((row >= 0) &&
448 (ToPlayground[YourColor][0][row] != CABLE_END) && (ActivationMap[YourColor][0][row] == INACTIVE)) {
449 NumCapsules[YOU]--;
450 CapsuleCurRow[YourColor] = 0;
451 ToPlayground[YourColor][0][row] = AMPLIFIER;
452 ActivationMap[YourColor][0][row] = ACTIVE1;
453 CapsuleCountdown[YourColor][0][row] = CAPSULE_COUNTDOWN40 * 2;
454
455 Takeover_Set_Capsule_Sound();
456
457 if (!NumCapsules[YOU]) {
458 /* You placed your last capsule ? let's speed up the end */
459 count_tick_len *= 0.75;
460 }
461 } /* if (row > 0 && ... ) */
462 }
463 /* if ( set ) */
464 ProcessCapsules(); /* count down the lifetime of the capsules */
465
466 ProcessPlayground();
467 ProcessPlayground();
468 ProcessPlayground();
469 ProcessPlayground(); /* this has to be done several times to be sure */
470
471 ProcessDisplayColumn();
472
473 }
474 /* if (motion_tick has occurred) */
475 ShowPlayground(target);
476 to_show_banner(count_text, NULL((void*)0));
477 our_SDL_flip_wrapper();
478 SDL_Delay(10);
479 } /* while !FinishTakeover */
480
481 /* Final countdown */
482 countdown = CAPSULE_COUNTDOWN40 + 10;
483
484 while (countdown--) {
485 // speed this up a little, some people get bored here...
486 // while ( SDL_GetTicks() < prev_count_tick + count_tick_len ) ;
487 // prev_count_tick += count_tick_len;
488 ProcessCapsules(); /* count down the lifetime of the capsules */
489 ProcessCapsules(); /* do it twice this time to be faster */
490 // AnimateCurrents ();
491 ProcessPlayground();
492 ProcessPlayground();
493 ProcessPlayground();
494 ProcessPlayground(); /* this has to be done several times to be sure */
495 ProcessDisplayColumn();
496 ShowPlayground(target);
497 our_SDL_flip_wrapper();
498 } /* while (countdown) */
499
500 return;
501
502}
503
504static void show_info_up_button() {
505 ShowGenericButtonFromList(UP_BUTTON);
506}
507
508static void show_info_down_button() {
509 ShowGenericButtonFromList(DOWN_BUTTON);
510}
511
512/**
513 * This function manages the whole takeover game of Tux against
514 * some bot.
515 *
516 * The return value is TRUE/FALSE depending on whether the game was
517 * finally won/lost.
518 * The function also writes the ratio of capsules the player needed to win (out of all of his capsules) into needed_capsules_ratio
519 * - Every capsule that has not been used within the game (numCapsules) is considered as not needed
520 * - For every conquered row that exceeds 7 (the minimal number of rows to win) one capsule is considered as not needed
521 */
522int droid_takeover(enemy *target, float *needed_capsules_ratio)
523{
524 int menu_finished = FALSE(0);
525 int reward = 0;
526 SDL_Event event;
527 static struct widget_text droid_info;
528
529 // Set up the droid description widget
530 widget_text_init(&droid_info, "");
531 init_droid_description(&droid_info, target->type);
532 widget_set_rect(WIDGET(&droid_info)((struct widget *)&droid_info), UNIVERSAL_COORD_W(258)(int)((float)(258) * ((float)(GameConfig . screen_width) / 640.0
))
, UNIVERSAL_COORD_H(107)(int)((float)(107) * ((float)(GameConfig . screen_height) / 480.0
))
, UNIVERSAL_COORD_W(346)(int)((float)(346) * ((float)(GameConfig . screen_width) / 640.0
))
, UNIVERSAL_COORD_H(282)(int)((float)(282) * ((float)(GameConfig . screen_height) / 480.0
))
);
533 droid_info.font = FPS_Display_BFont;
534 droid_info.content_above_func = show_info_up_button;
535 droid_info.content_below_func = show_info_down_button;
536
537 // Prevent distortion of framerate by the delay coming from
538 // the time spent in the menu.
539 Activate_Conservative_Frame_Computation();
540
541 // We set the UserRect to full again, no matter what other windows might
542 // be open right now...
543 User_Rect.x = 0;
544 User_Rect.y = 0;
545 User_Rect.w = GameConfig.screen_width;
546 User_Rect.h = GameConfig.screen_height;
547
548 while (SpacePressed() || MouseLeftPressed()) ; // make sure space is release before proceed
549
550 SwitchBackgroundMusicTo("Bleostrada.ogg");
551
552 while (!menu_finished) {
553 show_droid_info(target->type);
554 widget_text_display(WIDGET(&droid_info)((struct widget *)&droid_info));
555 ShowGenericButtonFromList(TAKEOVER_HELP_BUTTON);
556 SetCurrentFont(Para_BFont);
557 put_string_centered(Para_BFont, GameConfig.screen_height - 30, _("For more information, click the help button.")("For more information, click the help button."[0]!='\0'?dcgettext
(((void*)0), "For more information, click the help button.",
5):"")
);
558 blit_mouse_cursor();
559 our_SDL_flip_wrapper();
560
561 while (SDL_PollEvent(&event)) {
562
563 if (event.type == SDL_QUIT) {
564 Terminate(EXIT_SUCCESS0);
565 }
566
567 if (event.type == SDL_MOUSEBUTTONDOWN && event.button.button == SDL_BUTTON_LEFT1) {
568 if (MouseCursorIsOnButton(UP_BUTTON, GetMousePos_x(), GetMousePos_y())) {
569 droid_info.scroll_offset--;
570 } else if (MouseCursorIsOnButton(DOWN_BUTTON, GetMousePos_x(), GetMousePos_y())) {
571 droid_info.scroll_offset++;
572 } else if (MouseCursorIsOnButton(DROID_SHOW_EXIT_BUTTON, GetMousePos_x(), GetMousePos_y())) {
573 menu_finished = TRUE(1);
574 } else if (MouseCursorIsOnButton(TAKEOVER_HELP_BUTTON, GetMousePos_x(), GetMousePos_y())) {
575 display_takeover_help();
576 }
577 } else if (event.type == SDL_KEYDOWN
578 && ((event.key.keysym.sym == SDLK_SPACE) || (event.key.keysym.sym == SDLK_ESCAPE))) {
579 menu_finished = TRUE(1);
580 }
581 }
582 SDL_Delay(1);
583 }
584
585 while (!(!SpacePressed() && !EscapePressed() && !MouseLeftPressed())) ;
586
587 int player_capsules = 2 + Me.skill_level[get_program_index_with_name("Hacking")];
588 max_opponent_capsules = 2 + Droidmap[target->type].class;
589
590 if (do_takeover(player_capsules, max_opponent_capsules, 100, target)) {
591 /* Won takeover */
592 Me.marker = target->marker;
593
594 reward = Droidmap[target->type].experience_reward * Me.experience_factor;
595 Me.Experience += reward;
596 append_new_game_message(_("For taking control of your enemy, [s]%s[v], you receive %d experience.")("For taking control of your enemy, [s]%s[v], you receive %d experience."
[0]!='\0'?dcgettext (((void*)0), "For taking control of your enemy, [s]%s[v], you receive %d experience."
, 5):"")
, D_(target->short_description_text)(target->short_description_text[0]!='\0'?dcgettext ("freedroidrpg-data"
, target->short_description_text, 5):"")
, reward);
597
598 // Maybe the enemy in question was a kind of 'boss monster' or it had
599 // some special item, that is relevant to a mission or quest. In that
600 // case (like also when the bot is finally destroyed, the quest item
601 // should be dropped after the successful takeover process, even if the
602 // enemy isn't completely dead yet...
603 //
604 if (target->on_death_drop_item_code != (-1)) {
605 DropItemAt(target->on_death_drop_item_code, target->pos.z, target->pos.x, target->pos.y, 1);
606 target->on_death_drop_item_code = -1;
607 }
608
609 target->faction = FACTION_SELF;
610 target->has_been_taken_over = TRUE(1);
611
612 target->combat_state = WAYPOINTLESS_WANDERING;
613
614 // Always use the AfterTakeover dialog
615 free(target->dialog_section_name);
616 target->dialog_section_name = strdup("AfterTakeover")(__extension__ (__builtin_constant_p ("AfterTakeover") &&
((size_t)(const void *)(("AfterTakeover") + 1) - (size_t)(const
void *)("AfterTakeover") == 1) ? (((const char *) ("AfterTakeover"
))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({
size_t __len = strlen ("AfterTakeover") + 1; char *__retval =
(char *) malloc (__len); if (__retval != ((void*)0)) __retval
= (char *) memcpy (__retval, "AfterTakeover", __len); __retval
; })) : __strdup ("AfterTakeover")))
;
617
618 // When the bot is taken over, it should not turn hostile when
619 // the rest of his former combat group (identified by having the
620 // same marker) is attacked by the Tux.
621 //
622 target->marker = 0;
623 Me.TakeoverSuccesses[target->type]++;
624 } else {
625 Me.energy *= 0.5;
626 Me.TakeoverFailures[target->type]++;
627 }
628
629 clear_screen();
630
631 SwitchBackgroundMusicTo(CURLEVEL()(curShip.AllLevels[Me.pos.z])->Background_Song_Name);
632
633 if (LeaderColor == YourColor) {
634 // set the ratio of needed capsules out of all (player) capsules
635 // - Every capsule that has not been used within the game (numCapsules) is considered as not needed
636 // - For every conquered row that exceeds 7 (the minimal number of rows to win) one capsule is considered as not needed
637 *needed_capsules_ratio = 1 - (float)(NumCapsules[YOU] + LeaderCapsuleCount - 7) / (float)player_capsules;
638
639 return TRUE(1);
640 } else {
641 return FALSE(0);
642 }
643}; // int Takeover( int enemynum )
644
645/*-----------------------------------------------------------------
646 * This function performs the enemy movements in the takeover game,
647 * but it does this in an advanced way, that has not been there in
648 * the classic freedroid game.
649 *-----------------------------------------------------------------*/
650void AdvancedEnemyTakeoverMovements(const int countdown)
651{
652 // static int Actions = 3;
653 static int MoveProbability = 100;
654 static int TurnProbability = 10;
655 static int SetProbability = 80;
656
657 int action;
658 static int direction = 1; /* start with this direction */
659 int row = CapsuleCurRow[OpponentColor] - 1;
660 int test_row;
661 int test_value;
662
663 int BestTarget = -1;
664 float BestValue = (-10000); // less than any capsule can have
665
666 int endgame = 0;
667 if (countdown < NumCapsules[ENEMY]*7)
668 endgame = 1;
669
670#define TAKEOVER_MOVEMENT_DEBUG1 1
671
672 if (NumCapsules[ENEMY] == 0)
673 return;
674
675
676 if (GameConfig.difficulty_level!= DIFFICULTY_EASY){ //disable AI waiting on easy
677 // Wait for the player to move
678 if ((LeaderColor!=YourColor) && ((NumCapsules[YOU]-NumCapsules[ENEMY])>=0) && (!endgame) && (NumCapsules[ENEMY]<max_opponent_capsules))
679 return;
680 }
681
682 // First we're going to find out which target place is
683 // best choice for the next capsule setting.
684 //
685 for (test_row = 0; test_row < NUM_LINES12; test_row++) {
686 test_value = EvaluatePosition(OpponentColor, test_row, 1, endgame) + 0.01*test_row;
687 if (test_value > BestValue) {
688 BestTarget = test_row;
689 BestValue = test_value;
690 }
691 }
692 DebugPrintf(TAKEOVER_MOVEMENT_DEBUG1, "\nBest target row found : %d.", BestTarget);
693
694 if ((BestValue < 0.5) && (!endgame) && (LeaderColor==OpponentColor)) //it isn't worth it
695 return;
696
697 // Now we can start to move into the right direction.
698 // Previously this was a pure random choice like
699 //
700 // action = MyRandom (Actions);
701 //
702 // but now we do it differently :)
703 //
704 if (row < BestTarget) {
705 direction = 1;
706 action = 0;
707 } else if (row > BestTarget) {
708 direction = -1;
709 action = 0;
710 } else {
711 action = 2;
712 }
713
714 switch (action) {
715 case 0: /* Move along */
716 if (MyRandom(100) <= MoveProbability) {
717 row += direction;
718 if (row > NUM_LINES12 - 1)
719 row = 0;
720 if (row < 0)
721 row = NUM_LINES12 - 1;
722 }
723 break;
724
725 case 1: /* Turn around */
726 if (MyRandom(100) <= TurnProbability) {
727 direction *= -1;
728 }
729 break;
730 case 2: /* Try to set capsule */
731 if (MyRandom(100) <= SetProbability) {
732 if ((row >= 0) &&
733 (ToPlayground[OpponentColor][0][row] != CABLE_END) && (ActivationMap[OpponentColor][0][row] == INACTIVE)) {
734 NumCapsules[ENEMY]--;
735 Takeover_Set_Capsule_Sound();
736 ToPlayground[OpponentColor][0][row] = AMPLIFIER;
737 ActivationMap[OpponentColor][0][row] = ACTIVE1;
738 CapsuleCountdown[OpponentColor][0][row] = CAPSULE_COUNTDOWN40;
739 row = -1; /* For the next capsule: startpos */
740 }
741 else
742 {
743 row += direction;
Value stored to 'row' is never read
744 return;
745 }
746 }
747 /* if MyRandom */
748 break;
749
750 default:
751 break;
752
753 } /* switch action */
754
755 CapsuleCurRow[OpponentColor] = row + 1;
756
757 return;
758}; // AdvancedEnemyTakeoverMovements
759
760static void GetTakeoverGraphics(void)
761{
762 static int TakeoverGraphicsAreAlreadyLoaded = FALSE(0);
763 struct image img = EMPTY_IMAGE{ .surface = ((void*)0) , .offset_x = 0 , .offset_y = 0 , .texture_has_been_created
= 0 , .cached_transformation = { ((void*)0), 0.0, 0.0, { 0.0
, 0.0, 0.0, 0.0}, 0 } }
;
764 int i, j;
765 int curx = 0, cury = 0;
766 SDL_Rect tmp;
767
768 if (TakeoverGraphicsAreAlreadyLoaded)
769 return;
770
771 load_image(&img, TO_BLOCK_FILE"to_elem.png", FALSE(0));
772
773 // Get the fill-blocks
774 for (i = 0; i < NUM_FILL_BLOCKS3; i++, curx += FILL_BLOCK_LEN2*16 + 2) {
775 Set_Rect(tmp, curx, cury, FILL_BLOCK_LEN, FILL_BLOCK_HEIGHT){(tmp).x = (curx); (tmp).y = (cury); (tmp).w = (2*16); (tmp).
h = (2*7); }
;
776 create_subimage(&img, &FillBlocks[i], &tmp);
777 }
778
779 // Get the capsule blocks
780 for (i = 0; i < NUM_CAPS_BLOCKS3; i++, curx += CAPSULE_LEN2*7 + 2) {
781 Set_Rect(tmp, curx, cury, CAPSULE_LEN, CAPSULE_HEIGHT){(tmp).x = (curx); (tmp).y = (cury); (tmp).w = (2*7); (tmp).h
= (2*7); }
;
782 create_subimage(&img, &CapsuleBlocks[i], &tmp);
783 }
784
785 // Get the default background color, to be used when no background picture found!
786 curx = 0;
787 cury += FILL_BLOCK_HEIGHT2*7 + 2;
788
789 // get the game-blocks
790 for (j = 0; j < 2 * NUM_PHASES5; j++) {
791 for (i = 0; i < TO_BLOCKS11; i++) {
792 Set_Rect(tmp, curx, cury, TO_BLOCKLEN, TO_BLOCKHEIGHT){(tmp).x = (curx); (tmp).y = (cury); (tmp).w = (2*32); (tmp).
h = (2*8); }
;
793 create_subimage(&img, &ToGameBlocks[j * TO_BLOCKS11 + i], &tmp);
794 curx += TO_BLOCKLEN2*32 + 2;
795 }
796 curx = 0;
797 cury += TO_BLOCKHEIGHT2*8 + 2;
798 }
799
800 // Get the ground, column and leader blocks
801 for (i = 0; i < NUM_GROUND_BLOCKS6; i++) {
802 Set_Rect(tmp, curx, cury, GROUNDBLOCKLEN, GROUNDBLOCKHEIGHT){(tmp).x = (curx); (tmp).y = (cury); (tmp).w = (2*23); (tmp).
h = (2*8); }
;
803 create_subimage(&img, &ToGroundBlocks[i], &tmp);
804 curx += GROUNDBLOCKLEN2*23 + 2;
805 }
806 cury += GROUNDBLOCKHEIGHT2*8 + 2;
807 curx = 0;
808
809 // Now the rectangle for the column blocks will be set and after
810 // that we can create the new surface for blitting.
811 //
812 Set_Rect(tmp, curx, cury, COLUMNBLOCKLEN, COLUMNBLOCKHEIGHT){(tmp).x = (curx); (tmp).y = (cury); (tmp).w = (2*30); (tmp).
h = (2*8); }
;
813 create_subimage(&img, &ToColumnBlock, &tmp);
814
815 curx += COLUMNBLOCKLEN2*30 + 2;
816
817 // Now the rectangle for the leader block will be set and after
818 // that we can create the new surface for blitting.
819 //
820 Set_Rect(tmp, curx, cury, LEADERBLOCKLEN, LEADERBLOCKHEIGHT){(tmp).x = (curx); (tmp).y = (cury); (tmp).w = (2*30); (tmp).
h = (2*19); }
;
821 create_subimage(&img, &ToLeaderBlock, &tmp);
822
823 free_image_surface(&img);
824 TakeoverGraphicsAreAlreadyLoaded = TRUE(1);
825}
826
827/**
828 * Initiate the takeover game
829 * @param game_length game time in tenths of a second
830 * @param target a pointer to the enemy structure of the target. NULL means none
831 * @return 1 on player success, 0 on player failure
832 */
833int do_takeover(int player_capsules, int opponent_capsules, int game_length, enemy* target)
834{
835 char *message;
836 int player_won = 0;
837 int FinishTakeover = FALSE(0);
838 int row;
839 int old_status;
840
841 old_status = game_status;
842
843 Activate_Conservative_Frame_Computation();
844
845 // Maybe takeover graphics haven't been loaded yet. Then we do this
846 // here now and for once. Later calls will be ignored inside the function.
847 GetTakeoverGraphics();
848
849 // eat pending events
850 input_handle();
851
852 while (!FinishTakeover) {
853 // Init Color-column and Capsule-Number for each opponent and your color
854 //
855 for (row = 0; row < NUM_LINES12; row++) {
856 DisplayColumn[row] = (row % 2);
857 CapsuleCountdown[YELLOW][0][row] = -1;
858 CapsuleCountdown[PURPLE][0][row] = -1;
859 } // for row
860
861 YourColor = YELLOW;
862 OpponentColor = PURPLE;
863
864 CapsuleCurRow[YELLOW] = 0;
865 CapsuleCurRow[PURPLE] = 0;
866
867 NumCapsules[YOU] = player_capsules;
868 NumCapsules[ENEMY] = opponent_capsules;
869 InventPlayground();
870
871 EvaluatePlayground();
872
873 ShowPlayground(target);
874 our_SDL_flip_wrapper();
875
876 ChooseColor(target);
877
878 // This following function plays the takeover game, until one
879 // of THREE states is reached, i.e. until YOU WON, YOU LOST
880 // or until DEADLOCK is reached. Well, so maybe after that
881 // the takeover game is finished, but if it's a deadlock, then
882 // the game must be played again in the next loop...
883 //
884 PlayGame(game_length, target);
885
886 // We we evaluate the final score of the game. Maybe we're done
887 // already, maybe not...
888 //
889 if (LeaderColor == YourColor) {
890 Takeover_Game_Won_Sound();
891 message = _("Complete")("Complete"[0]!='\0'?dcgettext (((void*)0), "Complete", 5):""
)
;
892 FinishTakeover = TRUE(1);
893 player_won = 1;
894 } else if (LeaderColor == OpponentColor) {
895 Takeover_Game_Lost_Sound();
896 message = _("Rejected")("Rejected"[0]!='\0'?dcgettext (((void*)0), "Rejected", 5):""
)
;
897 FinishTakeover = TRUE(1);
898 player_won = 0;
899 } else {
900 Takeover_Game_Deadlock_Sound();
901 message = _("Deadlock")("Deadlock"[0]!='\0'?dcgettext (((void*)0), "Deadlock", 5):""
)
;
902 }
903
904 ShowPlayground(target);
905 to_show_banner(message, NULL((void*)0));
906 our_SDL_flip_wrapper();
907 SDL_Delay(100);
908
909 }
910
911 game_status = old_status;
912 return player_won;
913}
914
915/**
916 * Draws the playground for the takeover game
917 * @param target a pointer to the target's enemy structure. Use NULL for none
918 */
919static void ShowPlayground(enemy * target)
920{
921 int i, j;
922 int color, player;
923 int block;
924 int xoffs, yoffs;
925 SDL_Rect Target_Rect;
926 int phase, dheight;
927 xoffs = User_Rect.x + (User_Rect.w - 2 * 290) / 2;
928 yoffs = User_Rect.y + (User_Rect.h - 2 * 140) / 2 + 30;
929
930 phase = (int) Me.phase;
931
932 blit_background("console_bg1.jpg");
933
934 static struct image bg;
935 if (!image_loaded(&bg)) {
936 load_image(&bg, "backgrounds/takeover_console.png", FALSE(0));
937 }
938
939 display_image_on_screen(&bg, GameConfig.screen_width / 2 - 340, GameConfig.screen_height / 2 - 294, IMAGE_NO_TRANSFOset_image_transformation(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0));
940
941
942
943 if (target) {
944 // Find the difference of the droid's height and Tux's height.
945 // Tux's height is measured from the top of his head to the bottom of his feet
946 // This also accounts for the droid's blitting offset
947 struct tux_motion_class_images *current_motion_class_images = &tux_images[get_motion_class_id()];
948 dheight = current_motion_class_images->part_images[PART_GROUP_FEET][0][phase].offset_y +
949 current_motion_class_images->part_images[PART_GROUP_FEET][0][phase].h -
950 current_motion_class_images->part_images[PART_GROUP_HEAD][0][phase].offset_y -
951 enemy_images[target->type][0][0].h -
952 enemy_images[target->type][0][0].offset_y;
953
954 // Offset the droid's drawing rectangle by dheight minus 30 units.
955 Set_Rect(Target_Rect, xoffs + DroidStart[!YourColor].x + 50, yoffs + dheight - 80, User_Rect.w, User_Rect.h){(Target_Rect).x = (xoffs + DroidStart[!YourColor].x + 50); (
Target_Rect).y = (yoffs + dheight - 80); (Target_Rect).w = (User_Rect
.w); (Target_Rect).h = (User_Rect.h); }
;
956 PutIndividuallyShapedDroidBody(target, Target_Rect, FALSE(0), FALSE(0));
957 }
958 // SDL_SetColorKey (Screen, 0, 0);
959 SDL_SetClipRect(Screen, &User_Rect);
960
961 blit_tux(xoffs + DroidStart[YourColor].x + 20, yoffs - 25);
962
963 Set_Rect(Target_Rect, xoffs + LEFT_OFFS_X, yoffs + LEFT_OFFS_Y, User_Rect.w, User_Rect.h){(Target_Rect).x = (xoffs + 2*10); (Target_Rect).y = (yoffs +
2*15); (Target_Rect).w = (User_Rect.w); (Target_Rect).h = (User_Rect
.h); }
;
964
965 display_image_on_screen (&ToGroundBlocks[YELLOW_HIGH], Target_Rect.x, Target_Rect.y, IMAGE_NO_TRANSFOset_image_transformation(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0));
966
967 Target_Rect.y += GROUNDBLOCKHEIGHT2*8;
968
969 for (i = 0; i < 12; i++) {
970 display_image_on_screen (&ToGroundBlocks[YELLOW_MIDDLE], Target_Rect.x, Target_Rect.y, IMAGE_NO_TRANSFOset_image_transformation(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0));
971 Target_Rect.y += GROUNDBLOCKHEIGHT2*8;
972 }
973
974 display_image_on_screen (&ToGroundBlocks[YELLOW_LOW], Target_Rect.x, Target_Rect.y, IMAGE_NO_TRANSFOset_image_transformation(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0));
975
976 // the middle column
977 Set_Rect(Target_Rect, xoffs + MID_OFFS_X, yoffs + MID_OFFS_Y, 0, 0){(Target_Rect).x = (xoffs + 2*129); (Target_Rect).y = (yoffs +
2*8); (Target_Rect).w = (0); (Target_Rect).h = (0); }
;
978
979 display_image_on_screen (&ToLeaderBlock, Target_Rect.x, Target_Rect.y, IMAGE_NO_TRANSFOset_image_transformation(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0));
980
981 Target_Rect.y += LEADERBLOCKHEIGHT2*19;
982 for (i = 0; i < 12; i++, Target_Rect.y += COLUMNBLOCKHEIGHT2*8) {
983 display_image_on_screen (&ToColumnBlock, Target_Rect.x, Target_Rect.y, IMAGE_NO_TRANSFOset_image_transformation(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0));
984 }
985
986 // the right column
987 Set_Rect(Target_Rect, xoffs + RIGHT_OFFS_X, yoffs + RIGHT_OFFS_Y, 0, 0){(Target_Rect).x = (xoffs + 2*255); (Target_Rect).y = (yoffs +
2*15); (Target_Rect).w = (0); (Target_Rect).h = (0); }
;
988 display_image_on_screen (&ToGroundBlocks[PURPLE_HIGH], Target_Rect.x, Target_Rect.y, IMAGE_NO_TRANSFOset_image_transformation(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0));
989
990 Target_Rect.y += GROUNDBLOCKHEIGHT2*8;
991
992 for (i = 0; i < 12; i++, Target_Rect.y += GROUNDBLOCKHEIGHT2*8) {
993 display_image_on_screen (&ToGroundBlocks[PURPLE_MIDDLE], Target_Rect.x, Target_Rect.y, IMAGE_NO_TRANSFOset_image_transformation(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0));
994 }
995
996 display_image_on_screen (&ToGroundBlocks[PURPLE_LOW], Target_Rect.x, Target_Rect.y, IMAGE_NO_TRANSFOset_image_transformation(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0));
997
998 // Fill the leader-LED with its color
999 Set_Rect(Target_Rect, xoffs + LEADERLED_X, yoffs + LEADERLED_Y, 0, 0){(Target_Rect).x = (xoffs + 2*136); (Target_Rect).y = (yoffs +
2*11); (Target_Rect).w = (0); (Target_Rect).h = (0); }
;
1000 display_image_on_screen (&FillBlocks[LeaderColor], Target_Rect.x, Target_Rect.y, IMAGE_NO_TRANSFOset_image_transformation(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0));
1001
1002 Target_Rect.y += FILL_BLOCK_HEIGHT2*7;
1003 display_image_on_screen (&FillBlocks[LeaderColor], Target_Rect.x, Target_Rect.y, IMAGE_NO_TRANSFOset_image_transformation(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0));
1004
1005 // Fill the display column with its colors
1006 for (i = 0; i < NUM_LINES12; i++) {
1007 Set_Rect(Target_Rect, xoffs + LEDCOLUMN_X, yoffs + LEDCOLUMN_Y + i * (FILL_BLOCK_HEIGHT + 2), 0, 0){(Target_Rect).x = (xoffs + 2*136); (Target_Rect).y = (yoffs +
2*27 + i * (2*7 + 2)); (Target_Rect).w = (0); (Target_Rect).
h = (0); }
;
1008 display_image_on_screen (&FillBlocks[DisplayColumn[i]], Target_Rect.x, Target_Rect.y, IMAGE_NO_TRANSFOset_image_transformation(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0));
1009 }
1010
1011 // Show the yellow playground
1012 for (i = 0; i < NUM_LAYERS4 - 1; i++)
1013 for (j = 0; j < NUM_LINES12; j++) {
1014 Set_Rect(Target_Rect, xoffs + PlaygroundStart[YELLOW].x + i * TO_BLOCKLEN,{(Target_Rect).x = (xoffs + PlaygroundStart[YELLOW].x + i * 2
*32); (Target_Rect).y = (yoffs + PlaygroundStart[YELLOW].y + j
* 2*8); (Target_Rect).w = (0); (Target_Rect).h = (0); }
1015 yoffs + PlaygroundStart[YELLOW].y + j * TO_BLOCKHEIGHT, 0, 0){(Target_Rect).x = (xoffs + PlaygroundStart[YELLOW].x + i * 2
*32); (Target_Rect).y = (yoffs + PlaygroundStart[YELLOW].y + j
* 2*8); (Target_Rect).w = (0); (Target_Rect).h = (0); }
;
1016 block = ToPlayground[YELLOW][i][j] + ActivationMap[YELLOW][i][j] * TO_BLOCKS11;
1017 display_image_on_screen (&ToGameBlocks[block], Target_Rect.x, Target_Rect.y, IMAGE_NO_TRANSFOset_image_transformation(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0));
1018 }
1019
1020 // Show the purple playground
1021 for (i = 0; i < NUM_LAYERS4 - 1; i++)
1022 for (j = 0; j < NUM_LINES12; j++) {
1023 Set_Rect(Target_Rect,{(Target_Rect).x = (xoffs + PlaygroundStart[PURPLE].x + (4 - i
- 2) * 2*32); (Target_Rect).y = (yoffs + PlaygroundStart[PURPLE
].y + j * 2*8); (Target_Rect).w = (0); (Target_Rect).h = (0);
}
1024 xoffs + PlaygroundStart[PURPLE].x + (NUM_LAYERS - i - 2) * TO_BLOCKLEN,{(Target_Rect).x = (xoffs + PlaygroundStart[PURPLE].x + (4 - i
- 2) * 2*32); (Target_Rect).y = (yoffs + PlaygroundStart[PURPLE
].y + j * 2*8); (Target_Rect).w = (0); (Target_Rect).h = (0);
}
1025 yoffs + PlaygroundStart[PURPLE].y + j * TO_BLOCKHEIGHT, 0, 0){(Target_Rect).x = (xoffs + PlaygroundStart[PURPLE].x + (4 - i
- 2) * 2*32); (Target_Rect).y = (yoffs + PlaygroundStart[PURPLE
].y + j * 2*8); (Target_Rect).w = (0); (Target_Rect).h = (0);
}
;
1026 block = ToPlayground[PURPLE][i][j] + (NUM_PHASES5 + ActivationMap[PURPLE][i][j]) * TO_BLOCKS11;
1027 display_image_on_screen (&ToGameBlocks[block], Target_Rect.x, Target_Rect.y, IMAGE_NO_TRANSFOset_image_transformation(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0));
1028 }
1029
1030 // Show the capsules left for each player
1031 for (player = 0; player < 2; player++) {
1032 if (player == YOU)
1033 color = YourColor;
1034 else
1035 color = OpponentColor;
1036
1037 Set_Rect(Target_Rect, xoffs + CurCapsuleStart[color].x,{(Target_Rect).x = (xoffs + CurCapsuleStart[color].x); (Target_Rect
).y = (yoffs + CurCapsuleStart[color].y + CapsuleCurRow[color
] * (2*7 + 2)); (Target_Rect).w = (0); (Target_Rect).h = (0);
}
1038 yoffs + CurCapsuleStart[color].y + CapsuleCurRow[color] * (CAPSULE_HEIGHT + 2), 0, 0){(Target_Rect).x = (xoffs + CurCapsuleStart[color].x); (Target_Rect
).y = (yoffs + CurCapsuleStart[color].y + CapsuleCurRow[color
] * (2*7 + 2)); (Target_Rect).w = (0); (Target_Rect).h = (0);
}
;
1039 if (NumCapsules[player]) {
1040 display_image_on_screen (&CapsuleBlocks[color], Target_Rect.x, Target_Rect.y, IMAGE_NO_TRANSFOset_image_transformation(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0));
1041 }
1042
1043 for (i = 0; i < NumCapsules[player] - 1; i++) {
1044 Set_Rect(Target_Rect, xoffs + LeftCapsulesStart[color].x,{(Target_Rect).x = (xoffs + LeftCapsulesStart[color].x); (Target_Rect
).y = (yoffs + LeftCapsulesStart[color].y + i * 2*7); (Target_Rect
).w = (0); (Target_Rect).h = (0); }
1045 yoffs + LeftCapsulesStart[color].y + i * CAPSULE_HEIGHT, 0, 0){(Target_Rect).x = (xoffs + LeftCapsulesStart[color].x); (Target_Rect
).y = (yoffs + LeftCapsulesStart[color].y + i * 2*7); (Target_Rect
).w = (0); (Target_Rect).h = (0); }
;
1046 display_image_on_screen (&CapsuleBlocks[color], Target_Rect.x, Target_Rect.y, IMAGE_NO_TRANSFOset_image_transformation(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0));
1047 } // for capsules
1048 } // for player
1049
1050 return;
1051
1052}; // ShowPlayground
1053
1054/*-----------------------------------------------------------------
1055 * @Desc: Clears Playground (and ActivationMap) to default start-values
1056 * @Ret: void
1057 *
1058 *-----------------------------------------------------------------*/
1059void ClearPlayground(void)
1060{
1061 int color, layer, row;
1062
1063 for (color = YELLOW; color < TO_COLORS2; color++)
1064 for (layer = 0; layer < NUM_LAYERS4; layer++)
1065 for (row = 0; row < NUM_LINES12; row++) {
1066 ActivationMap[color][layer][row] = INACTIVE;
1067 if (layer < TO_COLORS2 - 1)
1068 ToPlayground[color][layer][row] = CABLE;
1069 else
1070 ToPlayground[color][layer][row] = INACTIVE;
1071 }
1072
1073 for (row = 0; row < NUM_LINES12; row++)
1074 DisplayColumn[row] = row % 2;
1075
1076}; // void ClearPlayground ( void )
1077
1078/* -----------------------------------------------------------------
1079 * This function generates a random playground for the takeover game
1080 * ----------------------------------------------------------------- */
1081void InventPlayground(void)
1082{
1083 int anElement;
1084 int newElement;
1085 int row, layer;
1086 int color = YELLOW;
1087
1088 // first clear the playground: we depend on this !!
1089 //
1090 ClearPlayground();
1091
1092 for (color = YELLOW; color < TO_COLORS2; color++) {
1093 for (layer = 1; layer < NUM_LAYERS4 - 1; layer++) {
1094 for (row = 0; row < NUM_LINES12; row++) {
1095 if (ToPlayground[color][layer][row] != CABLE)
1096 continue;
1097
1098 newElement = MyRandom(TO_ELEMENTS6 - 1);
1099 if (MyRandom(MAX_PROB100) > ElementProb[newElement]) {
1100 row--;
1101 continue;
1102 }
1103
1104 switch (newElement) {
1105 case EL_CABLE: /* has not to be set any more */
1106 anElement = ToPlayground[color][layer - 1][row];
1107 if (BlockClass[anElement] == NON_CONNECTOR1)
1108 ToPlayground[color][layer][row] = EMPTY;
1109 break;
1110
1111 case EL_CABLE_END:
1112 anElement = ToPlayground[color][layer - 1][row];
1113 if (BlockClass[anElement] == NON_CONNECTOR1)
1114 ToPlayground[color][layer][row] = EMPTY;
1115 else
1116 ToPlayground[color][layer][row] = CABLE_END;
1117 break;
1118
1119 case EL_AMPLIFIER:
1120 anElement = ToPlayground[color][layer - 1][row];
1121 if (BlockClass[anElement] == NON_CONNECTOR1)
1122 ToPlayground[color][layer][row] = EMPTY;
1123 else
1124 ToPlayground[color][layer][row] = AMPLIFIER;
1125 break;
1126
1127 case EL_COLOR_EXCHANGER:
1128 if (layer != 2) { /* only existing on layer 2 */
1129 row--;
1130 continue;
1131 }
1132
1133 anElement = ToPlayground[color][layer - 1][row];
1134 if (BlockClass[anElement] == NON_CONNECTOR1)
1135 ToPlayground[color][layer][row] = EMPTY;
1136 else
1137 ToPlayground[color][layer][row] = COLOR_EXCHANGER;
1138 break;
1139
1140 case EL_SEPARATOR:
1141 if (row > NUM_LINES12 - 3) {
1142 /* try again */
1143 row--;
1144 break;
1145 }
1146
1147 anElement = ToPlayground[color][layer - 1][row + 1];
1148 if (BlockClass[anElement] == NON_CONNECTOR1) {
1149 /* try again */
1150 row--;
1151 break;
1152 }
1153
1154 /* don't destroy branch in prev. layer */
1155 anElement = ToPlayground[color][layer - 1][row];
1156 if (anElement == SEPARATOR_H || anElement == SEPARATOR_L) {
1157 row--;
1158 break;
1159 }
1160 anElement = ToPlayground[color][layer - 1][row + 2];
1161 if (anElement == SEPARATOR_H || anElement == SEPARATOR_L) {
1162 row--;
1163 break;
1164 }
1165
1166 /* cut off cables in last layer, if any */
1167 anElement = ToPlayground[color][layer - 1][row];
1168 if (BlockClass[anElement] == CONNECTOR0)
1169 ToPlayground[color][layer - 1][row] = CABLE_END;
1170
1171 anElement = ToPlayground[color][layer - 1][row + 2];
1172 if (BlockClass[anElement] == CONNECTOR0)
1173 ToPlayground[color][layer - 1][row + 2] = CABLE_END;
1174
1175 /* set the branch itself */
1176 ToPlayground[color][layer][row] = SEPARATOR_H;
1177 ToPlayground[color][layer][row + 1] = SEPARATOR_M;
1178 ToPlayground[color][layer][row + 2] = SEPARATOR_L;
1179
1180 row += 2;
1181 break;
1182
1183 case EL_GATE:
1184 if (row > NUM_LINES12 - 3) {
1185 /* try again */
1186 row--;
1187 break;
1188 }
1189
1190 anElement = ToPlayground[color][layer - 1][row];
1191 if (BlockClass[anElement] == NON_CONNECTOR1) {
1192 /* try again */
1193 row--;
1194 break;
1195 }
1196 anElement = ToPlayground[color][layer - 1][row + 2];
1197 if (BlockClass[anElement] == NON_CONNECTOR1) {
1198 /* try again */
1199 row--;
1200 break;
1201 }
1202
1203 /* cut off cables in last layer, if any */
1204 anElement = ToPlayground[color][layer - 1][row + 1];
1205 if (BlockClass[anElement] == CONNECTOR0)
1206 ToPlayground[color][layer - 1][row + 1] = CABLE_END;
1207
1208 /* set the GATE itself */
1209 ToPlayground[color][layer][row] = GATE_H;
1210 ToPlayground[color][layer][row + 1] = GATE_M;
1211 ToPlayground[color][layer][row + 2] = GATE_L;
1212
1213 row += 2;
1214 break;
1215
1216 default:
1217 row--;
1218 break;
1219
1220 } /* switch NewElement */
1221
1222 } /* for row */
1223
1224 } /* for layer */
1225
1226 } /* for color */
1227
1228} /* InventPlayground */
1229
1230/* -----------------------------------------------------------------
1231 * This function generates a random playground for the takeover game
1232 * ----------------------------------------------------------------- */
1233void EvaluatePlayground(void)
1234{
1235 int newElement;
1236 int row, layer;
1237 int color = YELLOW;
1238 float ScoreFound[TO_COLORS2];
1239
1240#define EVALUATE_PLAYGROUND_DEBUG1 1
1241
1242 for (color = YELLOW; color < TO_COLORS2; color++) {
1243
1244 DebugPrintf(EVALUATE_PLAYGROUND_DEBUG1, "\n----------------------------------------------------------------------\n\
1245Starting to evaluate side nr. %d. Results displayed below:\n", color);
1246 ScoreFound[color] = 0;
1247
1248 for (layer = 1; layer < NUM_LAYERS4 - 1; layer++) {
1249 for (row = 0; row < NUM_LINES12; row++) {
1250
1251 // we examine this particular spot
1252 newElement = ToPlayground[color][layer][row];
1253
1254 switch (newElement) {
1255 case CABLE: /* has not to be set any more */
1256 case EMPTY:
1257 break;
1258
1259 case CABLE_END:
1260 DebugPrintf(EVALUATE_PLAYGROUND_DEBUG1, "CABLE_END found --> score -= 1.0\n");
1261 ScoreFound[color] -= 1.0;
1262 break;
1263
1264 case AMPLIFIER:
1265 DebugPrintf(EVALUATE_PLAYGROUND_DEBUG1, "AMPLIFIER found --> score += 0.5\n");
1266 ScoreFound[color] += 0.5;
1267 break;
1268
1269 case COLOR_EXCHANGER:
1270 DebugPrintf(EVALUATE_PLAYGROUND_DEBUG1, "COLOR_EXCHANGER found --> score -= 1.5\n");
1271 ScoreFound[color] -= 1.5;
1272 break;
1273
1274 case SEPARATOR_H:
1275 case SEPARATOR_L:
1276 case SEPARATOR_M:
1277 DebugPrintf(EVALUATE_PLAYGROUND_DEBUG1, "SEPARATOR found --> score += 1.0\n");
1278 ScoreFound[color] += 1.0;
1279 break;
1280
1281 case GATE_M:
1282 case GATE_L:
1283 case GATE_H:
1284 DebugPrintf(EVALUATE_PLAYGROUND_DEBUG1, "GATE found --> score -= 1.0\n");
1285 ScoreFound[color] -= 1.0;
1286 break;
1287
1288 default:
1289 DebugPrintf(EVALUATE_PLAYGROUND_DEBUG1, "UNHANDLED TILE FOUND!!\n");
1290 break;
1291
1292 } /* switch NewElement */
1293
1294 } /* for row */
1295
1296 } /* for layer */
1297
1298 DebugPrintf(EVALUATE_PLAYGROUND_DEBUG1, "\nResult for this side: %f.\n", ScoreFound[color]);
1299
1300 } /* for color */
1301
1302 DebugPrintf(EVALUATE_PLAYGROUND_DEBUG1, "\n----------------------------------------------------------------------\n");
1303
1304}; // EvaluatePlayground
1305
1306/* -----------------------------------------------------------------
1307 * This function Evaluates the AI side of the board for the takeover game
1308 * ----------------------------------------------------------------- */
1309float EvaluatePosition(const int color, const int row, const int layer, const int endgame)
1310{
1311 int player = YOU;
1312 if (color != YourColor)
1313 player = ENEMY;
1314
1315 int opp_color = YELLOW;
1316 if (opp_color == color)
1317 opp_color = PURPLE;
1318
1319 int newElement;
1320 // float ScoreFound [ TO_COLORS ];
1321
1322#define EVAL_DEBUG1 1
1323
1324 DebugPrintf(EVAL_DEBUG1, "\nEvaluatePlaygound ( %d , %d , %d ) called: ", color, row, layer);
1325
1326 if (layer == NUM_LAYERS4 - 1) {
1327 DebugPrintf(EVAL_DEBUG1, "End layer reached...");
1328 if (IsActive(color, row)) {
1329 DebugPrintf(EVAL_DEBUG1, "same color already active... returning 0.01 ");
1330 return (0.01*EvaluateCenterPosition(opp_color, row, layer, endgame));
1331 } else if (DisplayColumn[row] == color) {
1332 DebugPrintf(EVAL_DEBUG1, "same color... returning 0.05 ");
1333 return (0.05*EvaluateCenterPosition(opp_color, row, layer, endgame));
1334 } else if (IsActive(opp_color, row)) {
1335 DebugPrintf(EVAL_DEBUG1, "different color, but active... returning 9 ");
1336 if (endgame)
1337 return (90*EvaluateCenterPosition(opp_color, row, layer, endgame));
1338 else
1339 return (8*EvaluateCenterPosition(opp_color, row, layer, endgame));
1340 } else {
1341 DebugPrintf(EVAL_DEBUG1, "different color... returning 10 ");
1342 if (endgame)
1343 return (100*EvaluateCenterPosition(opp_color, row, layer, endgame));
1344 else
1345 return (10*EvaluateCenterPosition(opp_color, row, layer, endgame));
1346 }
1347 }
1348
1349 if (ActivationMap[color][layer][row] == ACTIVE1) { return (0); }
1350
1351 newElement = ToPlayground[color][layer][row];
1352
1353 switch (newElement) {
1354 case CABLE: /* has not to be set any more */
1355 DebugPrintf(EVAL_DEBUG1, "CABLE reached... continuing...");
1356 return (EvaluatePosition(color, row, layer + 1, endgame));
1357
1358 case AMPLIFIER:
1359 DebugPrintf(EVAL_DEBUG1, "AMPLIFIER reached... continuing...");
1360 return ((1 + (0.2 * NumCapsules[player])) * EvaluatePosition(color, row, layer + 1, endgame));
1361 break;
1362
1363 case COLOR_EXCHANGER:
1364 DebugPrintf(EVAL_DEBUG1, "COLOR_EXCHANGER reached... continuing...");
1365 return (-1.5 * EvaluatePosition(color, row, layer + 1, endgame));
1366 break;
1367
1368 case SEPARATOR_M:
1369 DebugPrintf(EVAL_DEBUG1, "SEPARATOR reached... double-continuing...");
1370 return (EvaluatePosition(color, row + 1, layer + 1, endgame) + EvaluatePosition(color, row - 1, layer + 1, endgame));
1371 break;
1372
1373 case GATE_H:
1374 DebugPrintf(EVAL_DEBUG1, "GATE reached... stopping...\n");
1375 if (ActivationMap[color][layer][row + 2] >= ACTIVE1) {
1376 return (5 * EvaluatePosition(color, row + 1, layer + 1, endgame));
1377 } else if (endgame) {
1378 return (0.5 * EvaluatePosition(color, row + 1, layer + 1, endgame));
1379 } else {
1380 return (0.3 * EvaluatePosition(color, row + 1, layer + 1, endgame));
1381 }
1382 break;
1383
1384 case GATE_L:
1385 DebugPrintf(EVAL_DEBUG1, "GATE reached... stopping...\n");
1386 if (ActivationMap[color][layer][row - 2] >= ACTIVE1) {
1387 return (5 * EvaluatePosition(color, row - 1, layer + 1, endgame));
1388 } else if (endgame) {
1389 return (0.5 * EvaluatePosition(color, row - 1, layer + 1, endgame));
1390 } else {
1391 return (0.3 * EvaluatePosition(color, row - 1, layer + 1, endgame));
1392 }
1393 break;
1394 //treat the following cases the same:
1395 case EMPTY:
1396 case CABLE_END:
1397 case SEPARATOR_H:
1398 case SEPARATOR_L:
1399 case GATE_M:
1400 return (0);
1401 break;
1402 default:
1403 DebugPrintf(EVAL_DEBUG1, "\nUNHANDLED TILE reached\n");
1404 break;
1405
1406 }
1407 return (0);
1408
1409};
1410
1411/* -----------------------------------------------------------------
1412 * This function Evaluates the Player side of the board from AI perspective
1413 * ----------------------------------------------------------------- */
1414float EvaluateCenterPosition(const int color, const int row, const int layer, const int endgame)
1415{
1416 int player = YOU; //should match the color owner (and be opposite the AI)
1417 if (color != YourColor)
1418 player = ENEMY;
1419
1420 int newElement;
1421
1422 if (layer == 1) {
1423 return (1); //hit the player's end
1424 }
1425
1426 newElement = ToPlayground[color][layer][row];
1427
1428 switch (newElement) {
1429 case CABLE: // has not to be set any more
1430 return (EvaluateCenterPosition(color, row, layer - 1, endgame));
1431 case AMPLIFIER:
1432 if (ActivationMap[color][layer+1][row] >= ACTIVE1) { //very low hope to take this over
1433 return (0.06);
1434 } else if (endgame) {
1435 return (1);
1436 } else {
1437 return ((1 - (0.1 * NumCapsules[player])) * EvaluateCenterPosition(color, row, layer - 1, endgame));
1438 }
1439 break;
1440 case SEPARATOR_H: //correctly evaluating this may lead to an infinite loop, using 0.5
1441 if ((NumCapsules[player]>0) && (!endgame))
1442 return ((0.53 - (0.02 * NumCapsules[player])) * EvaluateCenterPosition(color, row - 1, layer - 1, endgame) );
1443 else
1444 return (EvaluateCenterPosition(color, row - 1, layer - 1, endgame));
1445 break;
1446 case SEPARATOR_L:
1447 if ((NumCapsules[player]>0) && (!endgame))
1448 return ((0.53 - (0.02 * NumCapsules[player])) * EvaluateCenterPosition(color, row + 1, layer - 1, endgame) );
1449 else
1450 return (EvaluateCenterPosition(color, row + 1, layer - 1, endgame));
1451 break;
1452
1453 case GATE_M:
1454 if (!endgame)
1455 return ((0.5 + (0.09 * NumCapsules[player])) * (EvaluateCenterPosition(color, row + 1, layer - 1, endgame) + EvaluateCenterPosition(color, row - 1, layer - 1, endgame)));
1456 else
1457 return (1);
1458 break;
1459
1460 //Following cases act the same:
1461 case COLOR_EXCHANGER:
1462 case EMPTY:
1463 case CABLE_END:
1464 case SEPARATOR_M:
1465 case GATE_H:
1466 case GATE_L:
1467 if (!endgame)
1468 return (1 + (0.2 * NumCapsules[player]));
1469 else
1470 return (1);
1471 break;
1472 default:
1473 DebugPrintf(EVAL_DEBUG1, "\nUNHANDLED TILE reached\n");
1474 break;
1475 }
1476
1477 return (0);
1478
1479};
1480
1481/*-----------------------------------------------------------------
1482 * @Desc: process the playground following its intrinsic logic
1483 *
1484 * @Ret: void
1485 *
1486 *-----------------------------------------------------------------*/
1487void ProcessPlayground(void)
1488{
1489 int color, layer, row;
1490 int TurnActive = FALSE(0);
1491
1492 for (color = YELLOW; color < TO_COLORS2; color++) {
1493 for (layer = 1; layer < NUM_LAYERS4; layer++) {
1494 for (row = 0; row < NUM_LINES12; row++) {
1495 if (layer == NUM_LAYERS4 - 1) {
1496 if (IsActive(color, row))
1497 ActivationMap[color][layer][row] = ACTIVE1;
1498 else
1499 ActivationMap[color][layer][row] = INACTIVE;
1500
1501 continue;
1502 }
1503 /* if last layer */
1504 TurnActive = FALSE(0);
1505
1506 switch (ToPlayground[color][layer][row]) {
1507 case COLOR_EXCHANGER:
1508 case SEPARATOR_M:
1509 case GATE_H:
1510 case GATE_L:
1511 case CABLE:
1512 if (ActivationMap[color][layer - 1][row] >= ACTIVE1)
1513 TurnActive = TRUE(1);
1514 break;
1515
1516 case AMPLIFIER:
1517 if (ActivationMap[color][layer - 1][row] >= ACTIVE1)
1518 TurnActive = TRUE(1);
1519
1520 // additional enforcers stay active by themselves...
1521 if (ActivationMap[color][layer][row] >= ACTIVE1)
1522 TurnActive = TRUE(1);
1523
1524 break;
1525
1526 case CABLE_END:
1527 break;
1528
1529 case SEPARATOR_H:
1530 if (ActivationMap[color][layer][row + 1] >= ACTIVE1)
1531 TurnActive = TRUE(1);
1532 break;
1533
1534 case SEPARATOR_L:
1535 if (ActivationMap[color][layer][row - 1] >= ACTIVE1)
1536 TurnActive = TRUE(1);
1537 break;
1538
1539 case GATE_M:
1540 if ((ActivationMap[color][layer][row - 1] >= ACTIVE1)
1541 && (ActivationMap[color][layer][row + 1] >= ACTIVE1))
1542 TurnActive = TRUE(1);
1543
1544 break;
1545
1546 default:
1547 break;
1548 } /* switch */
1549
1550 if (TurnActive) {
1551 if (ActivationMap[color][layer][row] == INACTIVE)
1552 ActivationMap[color][layer][row] = ACTIVE1;
1553 } else
1554 ActivationMap[color][layer][row] = INACTIVE;
1555
1556 } /* for row */
1557
1558 } /* for layer */
1559
1560 } /* for color */
1561
1562 return;
1563}; // void ProcessPlayground ( void )
1564
1565/**
1566 * This function sets the correct values for the status column in the
1567 * middle of the takeover game field.
1568 * Blinking LEDs are realized here as well.
1569 */
1570void ProcessDisplayColumn(void)
1571{
1572 static int CLayer = 3; /* the connection-layer to the Column */
1573 static int flicker_color = 0;
1574 int row;
1575 int YellowCounter, PurpleCounter;
1576
1577 flicker_color = !flicker_color;
1578
1579 for (row = 0; row < NUM_LINES12; row++) {
1580 // unquestioned yellow
1581 if ((ActivationMap[YELLOW][CLayer][row] >= ACTIVE1) && (ActivationMap[PURPLE][CLayer][row] == INACTIVE)) {
1582 // change color?
1583 if (ToPlayground[YELLOW][CLayer - 1][row] == COLOR_EXCHANGER)
1584 DisplayColumn[row] = PURPLE;
1585 else
1586 DisplayColumn[row] = YELLOW;
1587 continue;
1588 }
1589 // clearly purple
1590 if ((ActivationMap[YELLOW][CLayer][row] == INACTIVE) && (ActivationMap[PURPLE][CLayer][row] >= ACTIVE1)) {
1591 // change color?
1592 if (ToPlayground[PURPLE][CLayer - 1][row] == COLOR_EXCHANGER)
1593 DisplayColumn[row] = YELLOW;
1594 else
1595 DisplayColumn[row] = PURPLE;
1596
1597 continue;
1598 }
1599 // undecided: flimmering
1600 if ((ActivationMap[YELLOW][CLayer][row] >= ACTIVE1) && (ActivationMap[PURPLE][CLayer][row] >= ACTIVE1)) {
1601 // change color?
1602 if ((ToPlayground[YELLOW][CLayer - 1][row] == COLOR_EXCHANGER) &&
1603 (ToPlayground[PURPLE][CLayer - 1][row] != COLOR_EXCHANGER))
1604 DisplayColumn[row] = PURPLE;
1605 else if ((ToPlayground[YELLOW][CLayer - 1][row] != COLOR_EXCHANGER) &&
1606 (ToPlayground[PURPLE][CLayer - 1][row] == COLOR_EXCHANGER))
1607 DisplayColumn[row] = YELLOW;
1608 else {
1609 if (flicker_color == 0)
1610 DisplayColumn[row] = YELLOW;
1611 else
1612 DisplayColumn[row] = PURPLE;
1613 } /* if - else if - else */
1614
1615 }
1616 /* if undecided */
1617 } /* for */
1618
1619 // evaluate the winning color
1620 YellowCounter = 0;
1621 PurpleCounter = 0;
1622 for (row = 0; row < NUM_LINES12; row++)
1623 if (DisplayColumn[row] == YELLOW)
1624 YellowCounter++;
1625 else
1626 PurpleCounter++;
1627
1628 LeaderCapsuleCount = (PurpleCounter > YellowCounter) ? PurpleCounter : YellowCounter;
1629 if (PurpleCounter < YellowCounter)
1630 LeaderColor = YELLOW;
1631 else if (PurpleCounter > YellowCounter)
1632 LeaderColor = PURPLE;
1633 else
1634 LeaderColor = DRAW;
1635
1636 return;
1637}; // void ProcessDisplayColumn
1638
1639/**
1640 * This function does the countdown of the capsules and kills them if
1641 * they are too old.
1642 */
1643void ProcessCapsules(void)
1644{
1645 int row;
1646 int color;
1647
1648 for (color = YELLOW; color <= PURPLE; color++)
1649 for (row = 0; row < NUM_LINES12; row++) {
1650 if (CapsuleCountdown[color][0][row] > 0)
1651 CapsuleCountdown[color][0][row]--;
1652
1653 if (CapsuleCountdown[color][0][row] == 0) {
1654 CapsuleCountdown[color][0][row] = -1;
1655 ActivationMap[color][0][row] = INACTIVE;
1656 ToPlayground[color][0][row] = CABLE;
1657 }
1658
1659 } /* for row */
1660
1661}; // void ProcessCapsules ( void )
1662
1663/**
1664 * This function tells, whether a Column-connection is active or not.
1665 * It returns TRUE or FALSE accordingly.
1666 */
1667int IsActive(int color, int row)
1668{
1669 int CLayer = 3; /* the connective Layer */
1670 int TestElement = ToPlayground[color][CLayer - 1][row];
1671
1672 if ((ActivationMap[color][CLayer - 1][row] >= ACTIVE1) && (BlockClass[TestElement] == CONNECTOR0))
1673 return TRUE(1);
1674 else
1675 return FALSE(0);
1676} /* IsActive */
1677
1678/* -----------------------------------------------------------------
1679 * This function animates the active cables: this is done by cycling
1680 * over the active phases ACTIVE1-ACTIVE3, which are represented by
1681 * different pictures in the playground
1682 * ----------------------------------------------------------------- */
1683void AnimateCurrents(void)
1684{
1685 int color, layer, row;
1686
1687 for (color = YELLOW; color <= PURPLE; color++)
1688 for (layer = 0; layer < NUM_LAYERS4; layer++)
1689 for (row = 0; row < NUM_LINES12; row++)
1690 if (ActivationMap[color][layer][row] >= ACTIVE1) {
1691 ActivationMap[color][layer][row]++;
1692 if (ActivationMap[color][layer][row] == NUM_PHASES5)
1693 ActivationMap[color][layer][row] = ACTIVE1;
1694 }
1695
1696 return;
1697}; // void AnimateCurrents (void)
1698
1699/**
1700 *
1701 *
1702 */
1703void to_show_banner(const char *left, const char *right)
1704{
1705 char left_box[LEFT_TEXT_LEN20 + 10];
1706 char right_box[RIGHT_TEXT_LEN6 + 10];
1707 int left_len, right_len; // the actual string lengths
1708
1709 // At first the text is prepared. This can't hurt.
1710 // we will decide whether to display it or not later...
1711 //
1712
1713 if (left == NULL((void*)0))
1714 left = "0";
1715
1716 if (right == NULL((void*)0)) {
1717 right = "";
1718 }
1719 // Now fill in the text
1720 left_len = strlen(left);
1721 if (left_len > LEFT_TEXT_LEN20) {
1722 printf("\nWarning: String %s too long for Left Infoline!!", left);
1723 Terminate(EXIT_FAILURE1);
1724 }
1725 right_len = strlen(right);
1726 if (right_len > RIGHT_TEXT_LEN6) {
1727 printf("\nWarning: String %s too long for Right Infoline!!", right);
1728 Terminate(EXIT_FAILURE1);
1729 }
1730 // Now prepare the left/right text-boxes
1731 memset(left_box, ' ', LEFT_TEXT_LEN20); // pad with spaces
1732 memset(right_box, ' ', RIGHT_TEXT_LEN6);
1733
1734 strncpy(left_box, left, left_len)__builtin_strncpy (left_box, left, left_len); // this drops terminating \0 !
1735 strncpy(right_box, right, right_len)__builtin_strncpy (right_box, right, right_len); // this drops terminating \0 !
1736
1737 left_box[LEFT_TEXT_LEN20] = '\0'; // that's right, we want padding!
1738 right_box[RIGHT_TEXT_LEN6] = '\0';
1739
1740 // Now the text should be ready and its
1741 // time to display it...
1742 DebugPrintf(2, "Takeover said: %s -- %s\n", left_box, right_box);
1743 SetCurrentFont(Para_BFont);
1744 display_text(left_box, LEFT_INFO_X(13*2), LEFT_INFO_Y(10*2), NULL((void*)0));
1745 display_text(right_box, RIGHT_INFO_X(242*2), RIGHT_INFO_Y(8*2), NULL((void*)0));
1746
1747}; // void to_show_banner (const char* left, const char* right)
1748
1749#undef _takeover_c