/* pile.c * * Card pile functions. These card pile functions are fairly low-level: They * require pointers to the pile_t structures to operate, which means that * player modules cannot use them to read or modify system-owned piles. Access * to piles is granted by higher-level functions that convert pile names to * pile pointers, check permissions, and send events. * * A pile is either a hand or a stack, where a hand is a set of cards visible * to only the owner and a stack is either completely face-down, has its top * face-up, or is face-up for all to see. * * Copyright (C) 2002 Andy Goth * Matt Harang * * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. */ #include #include #include "spite.h" /* TODO: Gracefully handle errors (but how...?) when being run as a Tcl command * or Python library. */ /* Returns a new empty pile constructed using the given parameters. */ pile_t* pile_new(int capacity, player_id_t owner, pile_name_t name, bool is_stack) { int i; pile_t* p = xmalloc(sizeof(pile_t)); p->cards = xmalloc(sizeof(card_t) * capacity); p->owner = owner; p->name = name; p->is_stack = is_stack; p->top = -1; for (i = 0; i < capacity; i++) p->cards[i] = card_empty; return p; } /* Deallocates a pile. */ void pile_del(pile_t* p) { free(p->cards); free(p); } /* Returns true if the pile is a stack or false if the pile is a hand. */ bool pile_is_stack(const pile_t* p) { return p->is_stack; } /* Returns true if the pile has no cards in it. */ bool pile_is_empty(const pile_t* p) { int i; if (pile_is_stack(p)) return p->top == -1; for (i = 0; i < p->capacity; i++) if (p->cards[i].exists) return 0; return 1; } /* Returns true if the pile has no room for more cards. */ bool pile_is_full(const pile_t* p) { int i; if (pile_is_stack(p)) return p->top == p->capacity - 1; for (i = 0; i < p->capacity; i++) if (!p->cards[i].exists) return 0; return 1; } /* Returns the number of cards in the pile. */ int pile_num_cards(const pile_t* p) { int i, count = 0; if (pile_is_stack(p)) return p->top + 1; for (i = 0; i < p->capacity; i++) if (p->cards[i].exists) count++; return count; } /* Adds a card to the pile. */ void pile_push(pile_t* p, card_t c) { int i; assert(!pile_is_full(p)); if (pile_is_stack(p)) p->cards[++p->top] = c; else for (i = 0; i < p->capacity; i++) if (!p->cards[i].exists) {p->cards[i] = c; break;} } /* Returns and removes the top card of the pile. */ card_t pile_pop(pile_t* p) { assert(pile_is_stack(p)); assert(!pile_is_empty(p)); return p->cards[p->top--]; } /* Returns the top card of the pile. */ card_t pile_peek(const pile_t* p) { assert(pile_is_stack(p)); return pile_is_empty(p) ? card_empty : p->cards[p->top]; } /* Returns the indexed card of the pile. */ card_t pile_peek_i(const pile_t* p, int i) { assert(i >= 0 && i < (pile_is_stack(p) ? p->top : p->capacity)); return p->cards[i]; } /* Moves a card from one pile to another. */ void pile_move_card(pile_t* src, pile_t* dst, int i) { card_t c; if (pile_is_stack(src)) c = pile_pop(src); else {c = pile_peek_i(src, i); src->cards[i].exists = 0;} pile_push(dst, c); } /* EOF */