public Card(Card c) { this.id = c.id; selected = false; mouseOver = false; texture = c.texture; z = x = y = 0; size = new Rectangle(x, y, 0, 0); owner = null; this.name = c.name; this.cost = c.cost; this.points = c.points; this.world = c.world; this.startingWorld = c.startingWorld; this.military = c.military; this.windfall = c.windfall; this.explore = c.explore; this.develop = c.develop; this.settle = c.settle; this.trade = c.trade; this.consume = c.consume; this.produce = c.produce; this.produceColor = c.produceColor; this.tempMilitary = c.tempMilitary; this.freeWorld = c.freeWorld; this.tradeThis = c.tradeThis; this.produceThisDraw = c.produceThisDraw; }
public void settlePhase(Card card, int index, int sectionNumber) { string message = ""; //We're selecting or deselecting a candidate cards to pay for our settlement if (sectionNumber == 4) { card.invertSelect(); //allow user to pick from section 5 if nothing in section 4 if (allSections[4].totalSelected < 1) { foreach (Card car in allSections[5]) if (car.hasBorder) { allSections[5].isSelectable = true; break; } } else allSections[5].isSelectable = false; //Make sure we've picked enough cards to settle the world, if we picked one if (allSections[6].totalSelected > 0 && (allSections[4].minSelectable > allSections[4].totalSelected)) allSections[7].isSelectable = false; else allSections[7].isSelectable = true; return; } if (sectionNumber == 6) { //we deselected a card, so clear out myPhase section and reset message, make sure confirm button is selectable if (card.selected) { card.select(false); allSections[4] = new Section(4, 0, this); allSections[4].maxSelectable = 0; allSections[4].minSelectable = 1; allSections[4].resetSection(); //Don't let them touch tableau unless candidate world is selected allSections[5].isSelectable = false; //Unselect anything in section 5 and remove borders foreach (Card car in allSections[5]) { car.hasBorder = false; if(car.selected) car.select(false); } appendErrorMessage("", true); } //Picking a world to settle else { if (!card.world) { message = "You must select a world, NOT a building."; appendErrorMessage(message, true); return; } card.select(true); //We've selected a card to develop, allow them to choose cards from tableau to use and discard but only if they have discard power if (card.military) { //Total normal military + rebel bonuses + specific color bonuses int totalMilitary = players.Peek().totalMilitary + Convert.ToInt16(card.rebel) * players.Peek().rebelHelp; //WHAT TO DO ABOUT PRODUCE COLOR? Add as separate attribute on card? if (!String.IsNullOrEmpty(card.windfall)) totalMilitary += players.Peek().settleSpecificMilitary[card.produceColor]; if (!String.IsNullOrEmpty(card.produce)) totalMilitary += players.Peek().settleSpecificMilitary[card.produceColor]; message = "You have selected " + card.name + ". It requires " + card.cost + " military to settle. You have " + totalMilitary + " military. "; //Not enough miltiary if (card.cost > totalMilitary) { allSections[7].isSelectable = false; message += "\nYou do not have enough military to conquer this world."; //If we don't have any cards to discard don't offer the option if (players.Peek().cardsWithTempMilitary < 1) { //Only offer contact specialists if military is insufficient if (players.Peek().payForMilitary) //do weird things { int cost = card.cost - players.Peek().settleReduce; message += "\nYou can pay for this military world using cards from your hand. Choose " + cost + " cards from to pay for it."; if (cost < 1) allSections[7].isSelectable = true; //copy over hand except for the card we selected allSections[4] = new Section(4, allSections[6], this); allSections[4].Remove(card); allSections[4].resetSection(); //setup phase section to handle developing the card that was selected allSections[4].maxSelectable = cost; allSections[4].minSelectable = cost; allSections[4].isSelectable = true; foreach (Card car in allSections[5]) { //IF HAS FREE WORLD POWER IN TABLEAU, highlight it if (car.freeWorld) { car.hasBorder = true; allSections[5].maxSelectable++; break; } } } appendErrorMessage(message, true); return; } //Otherwise setup discarding cards from tableau message += "You can discard a card from your tableau to gain more military."; //copy over any cards that can be discarded for military //allSections[4] = new Section(4, allSections[5].Count, this); foreach (Card car in allSections[5]) { //IF HAS TEMP MILITARY IN TABLEAU, highlight it if (car.tempMilitary > 0) { car.hasBorder = true; //Allow user to select multiple military discards allSections[5].maxSelectable++; } } allSections[5].minSelectable = 0; allSections[5].isSelectable = true; allSections[5].resetSection(); //Only offer contact specialists if military is insufficient if (players.Peek().payForMilitary) //do weird things { int cost = card.cost - players.Peek().settleReduce; message += "You can pay for this military world using cards from your hand. Choose " + cost + " cards from to pay for it."; if (cost < 1) allSections[7].isSelectable = true; //copy over hand except for the card we selected allSections[4] = new Section(4, allSections[6], this); allSections[4].Remove(card); allSections[4].resetSection(); //setup phase section to handle developing the card that was selected allSections[4].maxSelectable = cost; allSections[4].minSelectable = cost; allSections[4].isSelectable = true; foreach (Card car in allSections[5]) { //IF HAS FREE WORLD POWER IN TABLEAU, highlight it if (car.freeWorld) { car.hasBorder = true; allSections[5].maxSelectable++; break; } } } } //We have enough military to conquer this else { message += "\nTo conquer this world press continue."; allSections[7].isSelectable = true; } } //this is a regular world we must pay for with cards else { //cost of planet less normal reductions and color specific reductions int cost = card.cost - players.Peek().settleReduce; if (cost < 1) allSections[7].isSelectable = true; else allSections[7].isSelectable = false; if (!String.IsNullOrEmpty(card.windfall)) cost -= players.Peek().settleSpecificCost[card.produceColor]; if (!String.IsNullOrEmpty(card.produce)) cost -= players.Peek().settleSpecificCost[card.produceColor]; message = "You have selected " + card.name + ". Choose " + cost + " cards from to pay for it or choose a different card from your hand to settle."; //copy over hand except for the card we selected allSections[4] = new Section(4, allSections[6], this); allSections[4].Remove(card); allSections[4].resetSection(); //setup phase section to handle developing the card that was selected //always need to be able to select at least one -- WHY?? allSections[4].maxSelectable = cost; allSections[4].minSelectable = cost; allSections[4].isSelectable = true; foreach (Card car in allSections[5]) { //IF HAS FREE WORLD POWER IN TABLEAU, highlight it if (car.freeWorld) { car.hasBorder = true; allSections[5].minSelectable = 0; allSections[5].maxSelectable = 1; allSections[5].isSelectable = true; break; } } } appendErrorMessage(message, true); } return; } //Check if selected card from tableau else if (sectionNumber == 5) { Card tempCard = allSections[6][allSections[6].lastCardSelected]; //we deselected a card, so clear out myPhase section and reset message, make sure confirm button is selectable if (card.selected) { card.select(false); players.Peek().tempMilitary -= card.tempMilitary; //allow user to pick from section 4 if nothing in section 5 if(allSections[5].totalSelected < 1) allSections[4].isSelectable = true; int totalMilitary = players.Peek().totalMilitary + Convert.ToInt16(tempCard.rebel) * players.Peek().rebelHelp + players.Peek().tempMilitary; if (tempCard.cost > totalMilitary && tempCard.military) allSections[7].isSelectable = false; else if (card.freeWorld && !tempCard.military) allSections[7].isSelectable = false; //TODO:Need to update message to remove most recent line added in next else/if statements below } //Not a discardable card so ignore and throw warning else if (!card.hasBorder) { message = "This card cannot be used. Please select one of the highlighted cards."; appendErrorMessage(message, false); } //Assuming that card has either tempMilitary OR Free world ability, check for military ability if conquering military world else if (card.tempMilitary > 0) { card.select(true); //Don't allow them to select sections 4 and 5 allSections[4].isSelectable = false; //TODO: Need to add all selected cards to total military. Not just most recently clicked players.Peek().tempMilitary += card.tempMilitary; int totalMilitary = players.Peek().totalMilitary + Convert.ToInt16(tempCard.rebel) * players.Peek().rebelHelp + players.Peek().tempMilitary; //Display delta and total military for discarding this, wait for confirm message += "You can gain " + players.Peek().tempMilitary + " military for one turn by discarding these cards."; //TODO: properly update this error message message += "Then you will have " + totalMilitary + ". You require " + tempCard.cost + " military to settle " + tempCard.name + "."; message += "Press continue to discard."; //Not allowed to discard if still insufficient military. if (totalMilitary < tempCard.cost) { message += "This is not enough. Select more cards to discard or choose a different world to settle/conquer."; } else { message += "Press continue to discard."; allSections[7].isSelectable = true; } appendErrorMessage(message, false); } //OR check for free world ability if settling a normal world else if (card.freeWorld) { card.select(true); //Don't allow them to select sections 4 and 5 allSections[4].isSelectable = false; //Wait for confirm message = "You have selected " + card.name + ". It can be discarded to settle any world at 0 cost. "; message += "\nTo discard this card and settle the world, press continue."; allSections[7].isSelectable = true; appendErrorMessage(message, false); } return; } else if (sectionNumber != 7 || index != 0) return; //TODO: Make it so that continue button is not available unless enough things have been selected or military is high enough //button is confirm/select button if (skipPhase) { nextPhase(); return; } else if (allSections[6].totalSelected < 1) { //Players opts out of settling phase message = "No worlds selected. Not settling anything"; appendErrorMessage(message, true); nextPhase(); return; } else { Card tempCard = allSections[6][allSections[6].lastCardSelected]; message += "You have successfully settled/conquered " + tempCard.name + "."; appendErrorMessage(message, true); tempCard.select(false); //add card to tableau from hand allSections[6].Remove(tempCard); allSections[5].AddCard(tempCard); foreach (Card c in allSections[4]) if (c.selected) allSections[6].Remove(c); allSections[5].isSelectable = false; allSections[5].resetSection(); //reset tableau allSections[6].isSelectable = false; allSections[6].resetSection(); //reset hand //Draw card if we settled and have special power for (int i = 0; i < players.Peek().settleDrawAfter; i++) { players.Peek().addCardToHand(deck.Dequeue()); } if (players.Peek().settleDrawAfter > 0) message += "You drew " + players.Peek().settleDrawAfter + "cards after settling."; //Remove player temp cost reduction if (players.Peek().phaseSelected.Equals("III")) players.Peek().settleDrawAfter--; nextPhase(); } }
public void selectPhase(Card c, int index, int sectionNumber) { //We're selecting or deselecting a candidate action card if (sectionNumber == 4) { c.invertSelect(); if (allSections[4].totalSelected > 0) allSections[7].isSelectable = true; else allSections[7].isSelectable = false; return; } //Only other thing you can click in this phase is the confirm button else if (sectionNumber != 7 || index != 0) return; //not enough were selected so display error message and quit if (allSections[4].totalSelected < allSections[4].minSelectable) { string message = "You must select at least " + allSections[4].minSelectable + " cards."; appendErrorMessage(message,true); return; } //find card selected switch (allSections[4].lastCardSelected) { case 0: players.Peek().phaseSelected = "I"; phasesSelected[0] = true; break; case 1: players.Peek().phaseSelected = "I:2"; phasesSelected[0] = true; break; case 2: players.Peek().phaseSelected = "II"; phasesSelected[1] = true; break; case 3: players.Peek().phaseSelected = "III"; phasesSelected[2] = true; break; case 4: players.Peek().phaseSelected = "$"; phasesSelected[3] = true; break; case 5: players.Peek().phaseSelected = "IV"; phasesSelected[3] = true; break; case 6: players.Peek().phaseSelected = "V"; phasesSelected[4] = true; break; default: break; } allSections[4].isSelectable = false; string mess = "You have selected " + allSections[4].lastCardSelected; appendErrorMessage(mess, true); nextPhase(); }
public void explorePhase(Card card, int index, int sectionNumber) { //We're selecting or deselecting a candidate cards to add to our hand if (sectionNumber == 4) { card.invertSelect(); if (allSections[4].totalSelected < allSections[4].minSelectable) allSections[7].isSelectable = false; else allSections[7].isSelectable = true; return; } if (sectionNumber != 7 || index != 0) return; //No one picked this phase. wait for confirm button to advance if (skipPhase) { nextPhase(); return; } //Add cards we selected to keep to player's hand foreach (Card c in allSections[4]) if (c.selected) allSections[6].AddCard(new Card(c)); //line above ^^ should be player.addCardtoHand allSections[6].resetSection(); //reset hand allSections[4].isSelectable = false; appendErrorMessage("Success!", true); //go to next phase nextPhase(); }
public void developPhase(Card card, int index, int sectionNumber) { string message = ""; //We're selecting or deselecting a candidate cards to pay for our development if (sectionNumber == 4) { card.invertSelect(); if (allSections[6].totalSelected > 0 && (allSections[4].minSelectable > allSections[4].totalSelected)) allSections[7].isSelectable = false; else allSections[7].isSelectable = true; return; } //We're selecting or deselecting a candidate cards to build else if (sectionNumber == 6) { //we deselected a card, so clear out myPhase section and clear error message if (card.selected) { card.select(false); allSections[4] = new Section(4, 0, this); allSections[4].maxSelectable = 0; allSections[4].minSelectable = 1; allSections[4].resetSection(); allSections[7].isSelectable = true; appendErrorMessage("", true); } //Otherwise we selected a candidate card to develop else { //Develop phase is only for buldings if (card.world) { message = "You must select a building, NOT a world."; //This should be the only error possible right now so clear any pre-existing message appendErrorMessage(message, true); return; } int totalCost = (card.cost - players.Peek().developReduce); card.select(true); if (totalCost < 1) allSections[7].isSelectable = true; else allSections[7].isSelectable = false; message = "You have selected " + card.name + ". Choose " + (totalCost) + " cards from to pay for it or choose a different card from your hand to develop."; appendErrorMessage(message, true); //copy over hand except for the card we selected allSections[4] = new Section(4, allSections[6], this); allSections[4].Remove(card); allSections[4].resetSection(); //setup phase section to handle developing the card that was selected allSections[4].maxSelectable = totalCost; allSections[4].minSelectable = totalCost; allSections[4].isSelectable = true; } return; } //Did we hit the confirm/select button else if (sectionNumber != 7 || index != 0) return; if (skipPhase) { nextPhase(); return; } else if (allSections[6].totalSelected < 1) { //Players opts out of development phase message = "No buildings selected. Not developing anything"; appendErrorMessage(message, true); allSections[4].isSelectable = false; //TODO: does nextPhase belong here? I think no nextPhase(); } //Paying for card we've chosen else { Card tempCard = allSections[6][allSections[6].lastCardSelected]; message = "You have successfully developed " + tempCard.name + "."; appendErrorMessage(message, true); //add card to tableau from hand tempCard.select(false); allSections[5].AddCard(tempCard); allSections[6].Remove(tempCard); //these are cards we chose from section 4 to pay for development foreach (Card c in allSections[4]) if (c.selected) allSections[6].Remove(c); allSections[4].isSelectable = false; allSections[5].resetSection(); //reset tableau allSections[6].resetSection(); //reset hand //Draw card if we developed and have special power for (int i = 0; i < players.Peek().developDrawAfter; i++) { players.Peek().addCardToHand(deck.Dequeue()); } if (players.Peek().developDrawAfter > 0) message += "You drew " + players.Peek().developDrawAfter + "cards."; //Remove player temp cost reduction if (players.Peek().phaseSelected.Equals("II")) players.Peek().developReduce--; //go to next phase nextPhase(); } }
public void consumePhase(Card card, int index, int sectionNumber) { string message = ""; //We're selecting or deselecting a candidate cards to pay for our consume power if (sectionNumber == 4) { card.invertSelect(); //Make sure we've picked enough cards to satisfy the consume power //Probably should be it's own tag allSections[7][1].hasBorder = canCardBeConsumed(allSections[5][allSections[5].lastCardSelected]); return; } //Selecting or deselecting card with consume power else if (sectionNumber == 5) { //Deselecting a card if (card.selected) { card.select(false); allSections[4] = new Section(4, 0, this); allSections[4].isSelectable = false; allSections[4].resetSection(); } //Selecting a card else { //Check for consume power if (!card.hasBorder) { message = "This card doesn't have an available consume power. Pick a different one."; appendErrorMessage(message, true); return; } card.select(true); //copy over everything with a good allSections[4] = new Section(4, allSections[5].Count, this); //TODO: seutp other consume effects, not all cards will have consumPower!=null if(card.consumePower != null) validateConsumePower(card); else if (card.consumeAll) { //TODO: Notify user how they're about to lose all cards and gain X-1 VPs } allSections[4].resetSection(); } } //TODO: Decide if having a separate advance button would be helpful, I think it would if (sectionNumber != 7) return; //approximating card isSelectable using hasBorder if (!card.hasBorder) return; if (index == 1) { Card tempCard = allSections[5][allSections[5].lastCardSelected]; ConsumePowers tempPower = tempCard.consumePower; tempPower.usesLeft--; Player p = players.Peek(); if (tempPower.usesLeft < 1) { tempCard.hasBorder = false; p.myConsumePowers.Remove(tempPower); } //Remove cards from hand if (tempPower.typeOfGood.Equals("card")) { foreach (Card c in allSections[4]) { if (c.isSelected) { c.select(false); allSections[6].Remove(c); } } } else { foreach (Card c in allSections[4]) { if (c.isSelected) { c.select(false); allSections[4].Remove(c); allSections[5][allSections[5].IndexOf(c)].hasGood = false; } } } p.chipPoints += tempPower.vpReward; //Double VP if the player picked that phase and not discarding cards if (!tempPower.typeOfGood.Equals("card") && p.phaseSelected.Equals("$")) p.chipPoints += tempPower.vpReward; for (int i = 0; i < tempPower.cardReward; i++) { allSections[6].AddCard(deck.Dequeue()); } allSections[6].resetSection(); allSections[7][0].isSelectable = playerConsumeComplete(p); return; } if (index != 0) return; allSections[7].RemoveAt(1); //If successful remove borders foreach (Card c in allSections[5]) { c.hasBorder = false; } }
public void cardClicked(Card c, int cardIndex, int sectionNumber) { switch (currentPhase) { case "Selection": this.selectPhase(c, cardIndex, sectionNumber); break; case "Explore": this.explorePhase(c, cardIndex, sectionNumber); break; case "Develop": this.developPhase(c, cardIndex, sectionNumber); break; case "Settle": this.settlePhase(c, cardIndex, sectionNumber); break; case "Trade": this.tradePhase(c, cardIndex, sectionNumber); break; case "Consume": this.consumePhase(c, cardIndex, sectionNumber); break; case "Wait": nextPhase(); break; default: break; } }
public bool canCardBeConsumed(Card card) { //Make sure we've chosen enough goods/cards to consume if (allSections[4].minSelectable > allSections[4].totalSelected) return false; //Assume all typeOfGood's have been validated except different if (card.consumePower.typeOfGood.Equals("different")) { string typesOfGoods = ","; bool isDifferent = true; foreach (Card c in allSections[4]) { if (!c.selected) break; if (typesOfGoods.Contains(c.produceColor)) {isDifferent = false; break;} typesOfGoods += c.produceColor + ","; } if (!isDifferent) return false; } return true; }
public void validateConsumePower(Card card) { ConsumePowers tempPower = card.consumePower; switch (tempPower.typeOfGood) { case ("card"): foreach (Card c in allSections[6]) { allSections[4].AddCard(new Card(c)); } break; case ("any"): foreach (Card c in allSections[5]) { if (c.hasGood) allSections[4].AddCard(new Card(c)); } break; case ("different"): foreach (Card c in allSections[5]) { if (c.hasGood) allSections[4].AddCard(new Card(c)); } break; default: foreach (Card c in allSections[5]) { if (c.hasGood && c.produceColor.Equals(tempPower.typeOfGood)) allSections[4].AddCard(new Card(c)); } break; } //only allow people to do these one at a time, even if power can be used multiple times allSections[4].minSelectable = tempPower.numOfGoods; allSections[4].maxSelectable = tempPower.numOfGoods; }
public void tradePhase(Card card, int index, int sectionNumber) { string message = ""; //We're selecting or deselecting a candidate card to trade if (sectionNumber == 4) { card.invertSelect(); //Make sure we've picked enough cards to trade (always 1?) if (allSections[4].minSelectable > allSections[4].totalSelected) allSections[7].isSelectable = false; else allSections[7].isSelectable = true; return; } else if (sectionNumber != 7 && index != 0) { return; } //check color of good and draw that many cards for player int numCards = 2; numCards += players.Peek().tradeDraw + card.tradeThis; if (card.produceColor != null) numCards += players.Peek().tradeSpecific[card.produceColor]; for (int i = 0; i < numCards; i++) { allSections[6].AddCard(deck.Dequeue()); } allSections[6].resetSection(); card.hasGood = false; message = "You traded for " + numCards + " cards"; Game1.appendErrorMessage(message,true); nextPhase(); }
public void consumePhase(Card card, int index, int sectionNumber) { string message = ""; //We're selecting or deselecting a candidate cards to pay for our consume power if (sectionNumber == 4) { card.invertSelect(); //TODO: Make sure we've picked enough cards to satisfy the consume power //Probably should be it's own tag if (allSections[5].totalSelected > 0 && (allSections[4].minSelectable > allSections[4].totalSelected)) allSections[7].isSelectable = false; else allSections[7].isSelectable = true; return; } //Selecting or deselecting card with consume power else if (sectionNumber == 5) { //Deselecting a card if (card.selected) { card.select(false); allSections[4] = new Section(4, 0, this); allSections[4].isSelectable = false; allSections[4].resetSection(); } //Selecting a card else { //Check for consume power if (String.IsNullOrEmpty(card.consume)) { message = "This card doesn't have a consume power. Pick a different one."; appendErrorMessage(message, true); return; } card.select(true); //copy over everything with a good allSections[4] = new Section(4, allSections[5].Count, this); foreach (Card c in allSections[5]) { if (c.hasGood) allSections[4].AddCard(new Card(c)); } allSections[4].resetSection(); } } }
public void tradePhase(Card card, int index, int sectionNumber) { string message = ""; //We're selecting or deselecting a candidate card to trade if (sectionNumber == 4) { card.invertSelect(); //Make sure we've picked enough cards to trade (always 1?) if (allSections[4].minSelectable > allSections[4].totalSelected) allSections[7].isSelectable = false; else allSections[7].isSelectable = true; return; } else if (sectionNumber != 7 && index != 0) {return;} //check color of good and draw that many cards for player card.hasGood = false; int numCards = 2; for (int i = 0; i < numCards; i++) { players.Peek().AddCardToHand(deck.Dequeue()); } }
public void parseConsume(string str, Card c) { if (String.IsNullOrEmpty(str)) return; string[] split = str.Split(':'); if (split[0].Contains("lucky")) lucky = true; else if (split[0].Contains("all")) c.consumeAll = true; else if (split.Contains("draw")) consumeDraw += Int16.Parse(split[1]); else { c.consumePower = new ConsumePowers(split[0], split[1], split[2], split[3], split[4]); myConsumePowers.Add(c.consumePower); } //Consume powers should be assigned per Card, not per player (except consume draw and lucky) }
public void addCardToTableau(Card card) { card.owner = this; card.curSection = tableau; this.tableau.Add(card); //update special abilities //each power for a given phase is separated by a comma foreach (string str in card.explore.Split(',')) { parseExplore(str); } foreach (string str in card.develop.Split(',')) { parseDevelop(str); } foreach (string str in card.settle.Split(',')) { parseSettle(str); card.parseSettle(str); } foreach (string str in card.trade.Split(',')) { parseTrade(str); card.parseTrade(str); } foreach (string str in card.consume.Split(',')) { parseConsume(str, card); } foreach (string str in card.consume.Split(',')) { parseProduce(str); } //special stuff if (card.tempMilitary > 0) cardsWithTempMilitary++; //dirtyBit = false; }
public void addCardToHand(Card card) { card.owner = this; this.hand.Add(card); }