/* * Biloba * Copyright (C) 2004-2005 Guillaume Demougeot, Colin Leroy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ /** * Biloba - Q1 2005 * Game by Guillaume Demougeot * Code by Colin Leroy * * This file contains all pawn management code. */ #include #include #include #include "utils.h" #include "tile.h" #include "pawn.h" #include "layout.h" #include "sound.h" int pawn_get_max(void) { switch(game_num_players()) { case 2: return 16; case 3: case 4: return 8; default: assert(FALSE); return -1; } } #ifdef DEBUG char *pawn_color_str(PawnColor color) { assert(color >= 0 && color < PAWN_NUM_COLORS); switch(color) { case PAWN_ORANGE: return "PAWN_ORANGE"; case PAWN_BLUE: return "PAWN_BLUE"; case PAWN_RED: return "PAWN_RED"; case PAWN_GREEN: return "PAWN_GREEN"; default: assert(FALSE); return "PAWN_ERROR"; } } #endif static SDL_Surface *pawns_models[PAWN_NUM_COLORS] = {NULL}; static LList *my_pawns = NULL; static void init_pawns_models(void) { int i = 0; assert(pawns_models[PAWN_NUM_COLORS] == NULL); pawns_models[PAWN_ORANGE] = biloba_load_image("pawn-orange.png"); pawns_models[PAWN_BLUE] = biloba_load_image("pawn-blue.png"); pawns_models[PAWN_RED] = biloba_load_image("pawn-red.png"); pawns_models[PAWN_GREEN] = biloba_load_image("pawn-green.png"); for (i = 0; i < PAWN_NUM_COLORS; i++) assert(pawns_models[i] != NULL); } static Pawn *pawn_find(int num, PawnColor color) { LList *cur = my_pawns; while (cur) { Pawn *pawn = (Pawn *)cur->data; if (pawn->num == num && pawn->color == color) return pawn; cur = cur->next; } return NULL; } int pawn_count(PawnColor color) { LList *cur = my_pawns; int cnt = 0; while (cur) { Pawn *pawn = (Pawn *)cur->data; if (!pawn->eaten && pawn->color == color) cnt++; cur = cur->next; } return cnt; } LList *pawn_get_all(PawnColor color) { LList *cur = my_pawns; LList *results = NULL; while (cur) { Pawn *pawn = (Pawn *)cur->data; if (!pawn->eaten && pawn->color == color) results = llist_append(results, pawn); cur = cur->next; } return results; } static void pawn_get_coords(int num, PawnColor color, int *x, int *y) { int cnt = 0, tx = 0, ty = 0; assert(num >= 0 && num < pawn_get_max()); assert(color >= 0 && color < PAWN_NUM_COLORS); assert(x != NULL); assert(y != NULL); for (tx = 0; tx < MAX_TILES_X; tx++) { for (ty = 0; ty < MAX_TILES_Y; ty++) { if (game_num_players() == 2) { if (pos_2p[(int)color][ty][tx]) { if (cnt == num) { *x = tx; *y = ty; return; } cnt++; } } else { if (pos_4p[(int)color][ty][tx]) { if (cnt == num) { *x = tx; *y = ty; return; } cnt++; } } } } *x = -1; *y = -1; } static void pawn_update_coords(Pawn *pawn) { assert(pawn != NULL); pawn->coord_x = get_x(pawn->pos_x) + PAWN_OFFSET; pawn->coord_y = get_y(pawn->pos_y) + PAWN_OFFSET; } Pawn *pawn_get(int num, PawnColor color, int reinit) { Pawn *new_pawn = NULL; int x = 0, y = 0; assert(num >= 0 && num < pawn_get_max()); assert(color >= 0 && color < PAWN_NUM_COLORS); #ifdef DEBUG printf("pawn %d, %s\n", num, pawn_color_str(color)); #endif if (pawns_models[PAWN_ORANGE] == NULL) init_pawns_models(); if (pawn_find(num, color)) new_pawn = pawn_find(num, color); else { assert(reinit == TRUE); new_pawn = malloc(sizeof(Pawn)); my_pawns = llist_append(my_pawns, new_pawn); } if (reinit) { pawn_get_coords(num, color, &x, &y); new_pawn->num = num; new_pawn->color = color; new_pawn->eaten = FALSE; new_pawn->just_ate_on = NULL; new_pawn->pos_x = x; new_pawn->pos_y = y; new_pawn->surface = pawns_models[new_pawn->color]; if (x >= 0 && y >= 0) tile_get(x, y)->pawn = new_pawn; else new_pawn->eaten = TRUE; pawn_update_coords(new_pawn); } return new_pawn; } void pawn_free_all(void) { LList *pawns = my_pawns; for(; pawns; pawns = pawns->next) { Pawn *pawn = (Pawn *)pawns->data; free(pawn); pawn = NULL; } llist_free(my_pawns); my_pawns = NULL; } void pawn_draw (Pawn *pawn) { assert(pawn != NULL); put_image(pawn->surface, pawn->coord_x, pawn->coord_y); } Tile *pawn_get_tile(Pawn *pawn) { assert(pawn != NULL); if (pawn->eaten) return NULL; return tile_get(pawn->pos_x, pawn->pos_y); } LList *pawn_get_surroundings(Tile *tile) { LList *results = NULL; int ox, x = tile->pos_x - 1; int oy, y = tile->pos_y - 1; if (x < 0) x = 0; if (y < 0) y = 0; ox = x; oy = y; for (x = ox; x <= min(tile->pos_x + 1, MAX_TILES_X - 1); x++) { for (y = oy; y <= min(tile->pos_y + 1, MAX_TILES_Y - 1); y++) { Tile *ctile = tile_get(x, y); if (ctile == tile) continue; if (ctile->pawn) results = llist_append(results, ctile->pawn); } } return results; } void pawn_eat_fast(Pawn *pawn, int fast) { Tile *tile = pawn_get_tile(pawn); int i = 0; assert(pawn->eaten == FALSE); if (!fast) sound_play(SND_EAT); for (i = SDL_ALPHA_TRANSPARENT; !fast && i < SDL_ALPHA_OPAQUE; i++) { pawn_highlight(pawn, i); SDL_Delay(5); } pawn->eaten = TRUE; tile->pawn = NULL; tile_draw(tile); if (!fast) pawn_show_eaten(); } void pawn_eat(Pawn *pawn) { pawn_eat_fast(pawn, FALSE); } int pawn_try_and_eat(Pawn *start, Pawn *to_eat) { Tile *start_tile = pawn_get_tile(start); Tile *to_eat_tile = pawn_get_tile(to_eat); Tile *third_tile = tile_get_next_in_row(start_tile, to_eat_tile); Pawn *third = NULL; if (start->color == to_eat->color) return FALSE; if (third_tile == NULL) return FALSE; if (third_tile->type == TILE_NO_TILE || third_tile->type == TILE_CENTER) return FALSE; if (!third_tile->pawn) return FALSE; third = third_tile->pawn; if (third->color == start->color) { #ifdef DEBUG printf("adding %d %d and %d %d\n", start->coord_x, start->coord_y, third->coord_x, third->coord_y); #endif start->just_ate_on = llist_append(start->just_ate_on, to_eat_tile); third->just_ate_on = llist_append(third->just_ate_on, to_eat_tile); return TRUE; } return FALSE; } void pawn_move_to(Pawn *pawn, Tile *tile) { Tile *orig = NULL; assert(pawn != NULL); assert(tile != NULL); assert(pawn->eaten == FALSE); assert(tile->pawn == NULL); orig = pawn_get_tile(pawn); assert(orig != NULL); orig->pawn = NULL; pawn->pos_x = tile->pos_x; pawn->pos_y = tile->pos_y; pawn_update_coords(pawn); tile->pawn = pawn; tile_draw(orig); tile_draw(tile); } LList *pawn_get_replacement_pending_pawns(PawnColor color) { LList *results = NULL, *cur = pawn_get_all(color); while (cur) { Pawn *pawn = (Pawn *)cur->data; if (pawn->just_ate_on) { LList *tiles = pawn->just_ate_on; if (pawn->eaten) { /* pawn has been eaten, too bad!*/ llist_free(pawn->just_ate_on); pawn->just_ate_on = NULL; continue; } while (tiles) { Tile *tile = (Tile *)tiles->data; if (tile->pawn) { pawn->just_ate_on = llist_remove(pawn->just_ate_on, tile); tiles = pawn->just_ate_on; } if (tiles) tiles = tiles->next; } if (pawn->just_ate_on) { #ifdef DEBUG printf("pawn %d %d just ate\n", pawn->pos_x, pawn->pos_y); #endif results = llist_append(results, pawn); } } cur = cur->next; } return results; } void pawn_remove_just_eaten(Tile *tile) { LList *cur = my_pawns; while (cur) { Pawn *pawn = (Pawn *)cur->data; pawn->just_ate_on = llist_remove(pawn->just_ate_on, tile); cur = cur->next; } } void pawn_highlight(Pawn *pawn, int value) { static SDL_Surface *highlighter = NULL; Tile *tile = pawn_get_tile(pawn); if (!highlighter) { highlighter = biloba_load_image("pawn-highlighter.png"); assert(highlighter != NULL); } SDL_SetAlpha(highlighter, SDL_SRCALPHA, value); assert(tile != NULL); if (value) put_image(highlighter, tile->coord_x + PAWN_OFFSET, tile->coord_y + PAWN_OFFSET); if (is_playing()) { SDL_UpdateRect(screen, tile->coord_x + PAWN_OFFSET, tile->coord_y + PAWN_OFFSET, 30, 30); } } void pawn_show_eaten(void) { int cur_eaten[4] = {0, 0, 0, 0}; LList *cur = my_pawns; for (; cur ; cur = cur->next) { Pawn *pawn = (Pawn *)cur->data; int offset = (35 * ((int)pawn->color + 1)); int pos_x; int pos_y; if ((int)pawn->color >= game_num_players()) continue; if (pawn->num >= pawn_get_max()) continue; if (!pawn->eaten) continue; cur_eaten[(int)pawn->color]++; pos_x = XS - offset; pos_y = 10 + (35 * (cur_eaten[(int)pawn->color]-1)); if (cur_eaten[(int)pawn->color] > pawn_get_max()) continue; #ifdef DEBUG printf("putting pawn at %d %d\n", pos_x, pos_y); #endif put_image(pawn->surface, pos_x, pos_y); } SDL_UpdateRect(screen, XS - 160, 0, 159, 599); }