function Player(number, type) {
  this.number = number;
  this.type = type;
  this.vp = 0;
  this.buildings = new Array();
  this.hand = new Array();
  this.purple = new Array(false,false,false,false,false,false,false,false,false,false,false,false,
                          false,false,false,false,false,false,false,false,false,false,false,false,
                          false,false,false,false,false);
  this.chapel_vp = 0;
  this.build_new = false;
  this.build_cantBuild = new Array();
  this.build_discount = 0;
  this.build_crane = -1;



  this.decideRole = function() {
    var weights = new Array(0, 0, 0, 0, 0);
    var i, my_produce_capacity = 0, my_trade_capacity = 0, his_produce_capacity = 0, his_trade_capacity = 0;
    if (this.type == "computer") {
      for (i=0; i<this.buildings.length; i++) {
        if (this.buildings[i].type == 'p') {
          if (this.buildings[i].gold) {
            my_trade_capacity++;
          } else {
            my_produce_capacity++;
          }
        }
      }
      for (i=0; i<player[0].buildings.length; i++) {
        if (player[0].buildings[i].type == 'p') {
          if (player[0].buildings[i].gold) {
            his_trade_capacity++;
          } else {
            his_produce_capacity++;
          }
        }
      }
      weights[ROLE_COUNCILLOR] += this.purple[CARD_ARCHIVE] ? 3 : 0;
      weights[ROLE_COUNCILLOR] += this.purple[CARD_PREFECTURE] ? 5 : 0;
      weights[ROLE_BUILDER] += this.purple[CARD_BLACK_MARKET] ? 1 : 0;
      weights[ROLE_BUILDER] += this.purple[CARD_CARPENTER] ? 2 : 0;
      weights[ROLE_BUILDER] += this.purple[CARD_CRANE] ? 1 : 0;
      weights[ROLE_BUILDER] += this.purple[CARD_POOR_HOUSE] ? 1 : 0;
      weights[ROLE_BUILDER] += this.purple[CARD_QUARRY] ? 2 : 0;
      weights[ROLE_BUILDER] += this.purple[CARD_SMITHY] ? 1 : 0;
      weights[ROLE_PRODUCER] += this.purple[CARD_AQUEDUCT] ? 5 : 0;
      weights[ROLE_PRODUCER] += this.purple[CARD_WELL] ? 3 : 0;
      weights[ROLE_TRADER] += this.purple[CARD_MARKET_HALL] ? 4 : 0;
      weights[ROLE_TRADER] += this.purple[CARD_MARKET_STAND] ? 2 : 0;
      weights[ROLE_TRADER] += this.purple[CARD_TRADING_POST] ? 2 : 0;
      weights[ROLE_PROSPECTOR] += this.purple[CARD_GOLD_MINE] ? 6 : 0;
      weights[ROLE_COUNCILLOR] += !player[0].purple[CARD_ARCHIVE] ? 1 : 0;
      weights[ROLE_COUNCILLOR] += !player[0].purple[CARD_PREFECTURE] ? 2 : 0;
      weights[ROLE_BUILDER] += !player[0].purple[CARD_BLACK_MARKET] ? .5 : 0;
      weights[ROLE_BUILDER] += !player[0].purple[CARD_CARPENTER] ? 1 : 0;
      weights[ROLE_BUILDER] += !player[0].purple[CARD_CRANE] ? .5 : 0;
      weights[ROLE_BUILDER] += !player[0].purple[CARD_POOR_HOUSE] ? .5 : 0;
      weights[ROLE_BUILDER] += !player[0].purple[CARD_QUARRY] ? 1 : 0;
      weights[ROLE_BUILDER] += !player[0].purple[CARD_SMITHY] ? .5 : 0;
      weights[ROLE_PRODUCER] += !player[0].purple[CARD_AQUEDUCT] ? 2 : 0;
      weights[ROLE_PRODUCER] += !player[0].purple[CARD_WELL] ? 1 : 0;
      weights[ROLE_TRADER] += !player[0].purple[CARD_MARKET_HALL] ? 2 : 0;
      weights[ROLE_TRADER] += !player[0].purple[CARD_MARKET_STAND] ? 1 : 0;
      weights[ROLE_TRADER] += !player[0].purple[CARD_TRADING_POST] ? 1 : 0;
      weights[ROLE_PROSPECTOR] += !player[0].purple[CARD_GOLD_MINE] ? 3 : 0;
      weights[ROLE_BUILDER] += (this.hand.length > 4) ? 2 : 0
      weights[ROLE_BUILDER] += (this.hand.length > 5) ? 2 : 0
      weights[ROLE_BUILDER] += (this.hand.length > 6) ? 2 : 0
      weights[ROLE_BUILDER] += (this.hand.length > 7) ? 2 : 0
      weights[ROLE_BUILDER] += (player[0].hand.length < 3) ? 1 : 0
      weights[ROLE_BUILDER] += (player[0].hand.length < 2) ? 2 : 0
      weights[ROLE_PRODUCER] -=  (my_produce_capacity == 0) ? 20 : 0;
      weights[ROLE_PRODUCER] +=  (my_produce_capacity > 1) ? 1 : 0;
      weights[ROLE_PRODUCER] += (my_produce_capacity > his_produce_capacity) ? 2 : 0;
      weights[ROLE_TRADER] -= (my_trade_capacity == 0) ? 20 : 0;
      weights[ROLE_TRADER] += (my_trade_capacity > 1) ? 1 : 0;
      weights[ROLE_TRADER] += (my_trade_capacity > his_trade_capacity) ? 2 : 0;
      weights[ROLE_COUNCILLOR] += 2;
      weights[ROLE_PROSPECTOR] += 2;
      weights[ROLE_PROSPECTOR] += (this.hand.length < 3) ? 1 : 0;
      weights[ROLE_PROSPECTOR] += (this.hand.length < 2) ? 2 : 0;
      weights[ROLE_COUNCILLOR] = (roles[ROLE_COUNCILLOR].isNew) ? weights[ROLE_COUNCILLOR] : -100;
      weights[ROLE_BUILDER] = (roles[ROLE_BUILDER].isNew) ? weights[ROLE_BUILDER] : -100;
      weights[ROLE_PRODUCER] = (roles[ROLE_PRODUCER].isNew) ? weights[ROLE_PRODUCER] : -100;
      weights[ROLE_TRADER] = (roles[ROLE_TRADER].isNew) ? weights[ROLE_TRADER] : -100;
      weights[ROLE_PROSPECTOR] = (roles[ROLE_PROSPECTOR].isNew) ? weights[ROLE_PROSPECTOR] : -100;
//document.getElementById("debug").innerHTML += "Weights: " + weights[0] + " " + weights[1] + " " + weights[2] + " " +
//weights[3] + " " + weights[4] + "<br>";

      if ((weights[ROLE_BUILDER] >= weights[ROLE_COUNCILLOR]) &&
          (weights[ROLE_BUILDER] >= weights[ROLE_PRODUCER]) &&
          (weights[ROLE_BUILDER] >= weights[ROLE_TRADER]) &&
          (weights[ROLE_BUILDER] >= weights[ROLE_PROSPECTOR])) {
        this.selectRole(ROLE_BUILDER);
      } else if ((weights[ROLE_PRODUCER] >= weights[ROLE_COUNCILLOR]) &&
                 (weights[ROLE_PRODUCER] >= weights[ROLE_TRADER]) &&
                 (weights[ROLE_PRODUCER] >= weights[ROLE_PROSPECTOR])) {
        this.selectRole(ROLE_PRODUCER);
      } else if ((weights[ROLE_TRADER] >= weights[ROLE_COUNCILLOR]) &&
                 (weights[ROLE_TRADER] >= weights[ROLE_PROSPECTOR])) {
        this.selectRole(ROLE_TRADER);
      } else if (weights[ROLE_PROSPECTOR] >= weights[ROLE_COUNCILLOR]) {
        this.selectRole(ROLE_PROSPECTOR);
      } else {
        this.selectRole(ROLE_COUNCILLOR);
      }
    }
  }



  this.selectRole = function(roleNumber) {
    var txtPlayerNumber = this.number + 1;
    if ((turn % 2 == this.number) && roles[roleNumber].isNew) {
      roles[roleNumber].setToUsed();
      switch (roleNumber) {
        case ROLE_COUNCILLOR:
          history("Player " + txtPlayerNumber + " selected councillor role.");
          this.council(1);
          break;
        case ROLE_BUILDER:
          history("Player " + txtPlayerNumber + " selected builder role.");
          this.build(1);
          break;
        case ROLE_PRODUCER:
          history("Player " + txtPlayerNumber + " selected producer role.");
          this.produce(1);
          break;
        case ROLE_TRADER:
          history("Player " + txtPlayerNumber + " selected trader role.");
          this.trade(1);
          break;
        case ROLE_PROSPECTOR:
          history("Player " + txtPlayerNumber + " selected prospector role.");
          this.prospect(1);
          break;
      }
    }
  }



  this.chapel = function(step) {
    if (this.type == "human") {
      this.chapelHuman(step);
    } else if (this.type == "computer") {
      this.chapelComputer(step);
    }
  }
  this.chapelHuman = function(step) {
    if ((step == 1) && (this.hand.length == 0)) {
      endRound(3);
    } else if (step == 1) {
      chooser.start(this.hand, 1, false, ROLE_CHAPEL, 2, "Select a card to place under the chapel.");
    } else if (step == 2) {
      if (chooser.picked.length == 1) {
        this.hand = chooser.notPicked;
        this.refreshHand();
        this.chapel_vp++;
      }
      endRound(3);
    }
  }
  this.chapelComputer = function(step) {
    if (this.hand.length > 0) {
      this.hand.sort(costCompareFunction);
      this.hand.pop();
      this.refreshHand();
      this.chapel_vp++;
      window.alert("Player 2 placed a card under his chapel.");
    }
  }



  this.cardCheck = function(step) {
    var safe = 7;
    if (this.purple[CARD_TOWER]) {
      safe = 12;
    }
    if (this.type == "human") {
      this.cardCheckHuman(step, safe);
    } else if (this.type == "computer") {
      this.cardCheckComputer(step, safe);
    }
  }
  this.cardCheckHuman = function(step, safe) {
    if (step == 1) {
      if (this.hand.length > safe) {
        chooser.start(this.hand, safe, true, ROLE_CARDCHECK, 2, "Select cards to keep.");
      } else {
        endRound(4);
      }
    } else if (step == 2) {
      for (var i=0; i<chooser.notPicked; i++) {
        deck.discard(chooser.notPicked[i]);
      }
      this.hand = chooser.picked;
      this.refreshHand();
      endRound(4);
    }
  }
  this.cardCheckComputer = function(step, safe) {
    if (this.hand.length > safe) {
      this.hand.sort(costCompareFunction);
      while (this.hand.length > safe) {
        foo = this.hand.pop();
      }
    }
    this.refreshHand();
  }



  this.council = function(step) {
    var cardsToKeep = 1;
    var cardsToDraw = (turn % 2 == this.number) ? 5 : 2;
    if ((turn % 2 == this.number) && this.purple[CARD_LIBRARY]) {
      cardsToDraw = cardsToDraw + 3;
    }
    if (this.purple[CARD_PREFECTURE]) {
      cardsToKeep = cardsToKeep + 1;
    }
    if (this.type == "human") {
      this.councilHuman(step, cardsToDraw, cardsToKeep)
    } else if (this.type == "computer") {
      this.councilComputer(step, cardsToDraw, cardsToKeep);
    }
  }
  this.councilHuman = function(step, cardsToDraw, cardsToKeep) {
    var i;
    var choices = new Array();
    if (step == 1) {
      // Archive
      if (this.purple[CARD_ARCHIVE]) {
        for (i=0; i<this.hand.length; i++) {
          choices.push(this.hand[i]);
        }
        cardsToKeep = cardsToKeep + this.hand.length;
      }
      // Draw cards
      for (i=0; i<cardsToDraw; i++) {
        choices.push(deck.draw());
      }
      chooser.start(choices, cardsToKeep, true, ROLE_COUNCILLOR, 2, "Councillor Phase: Select card(s) to keep.");
    } else if (step == 2) {
      if (this.purple[CARD_ARCHIVE]) {
        this.hand = new Array();
        this.refreshHand();
      }
      for (i=0; i<chooser.picked.length; i++) {
        this.newCard(chooser.picked[i]);
      }
      for (i=0; i<chooser.notPicked.length; i++) {
        deck.discard(chooser.notPicked[i]);
      }
      if (turn % 2 == this.number) {
        player[1].council(1);
      } else {
        endRound(1);
      }
    }
  }
  this.councilComputer = function(step, cardsToDraw, cardsToKeep) {
    // AI: Archive not implemented
    var i, selected;
    var choices = new Array();
    var choicesP = new Array();
    var choicesV = new Array();
    var choicesD = new Array();
    // Generate choices
    for (i=0; i<cardsToDraw; i++) {
      choices.push(deck.draw());
    }
    this.decideCardToKeep(choices, cardsToKeep)
    if (turn % 2 == this.number) {
      player[0].council(1);
    } else {
      endRound(1);
    }
  }



  this.build = function(step) {
    if (step == 8) {
      if (this.purple[CARD_POOR_HOUSE] && (this.hand.length <= 1) && (this.build_new.id != CARD_POOR_HOUSE)) {
        this.newCard(deck.draw());
      }
      if (this.purple[CARD_CARPENTER] && (this.build_new.type == 'v') && (this.build_new.id != CARD_CARPENTER)) {
        this.newCard(deck.draw());
      }
      this.refreshHand();
      this.build(9);
    } else {
      if (this.type == "human") {
        this.buildHuman(step);
      } else if (this.type == "computer") {
        this.buildComputer(step);
      }
    }
  }
  this.buildHuman = function(step) {
    var i, actual_cost, choices, option;
    if (step == 1) {
      this.build_discount = 0;
      this.build_crane = -1;
      choices = new Array();
      for (i=0; i<this.buildings.length; i++) {
        if (this.buildings[i].id != CARD_CRANE) {
          choices.push(this.buildings[i]);
        }
      }
      if (this.purple[CARD_CRANE] && (choices.length > 0) && (this.hand.length > 0)) {
        chooser.start(choices, 1, false, ROLE_BUILDER, 2, "Builder Phase: Use crane to build over?");
      } else {
        this.build(3);
      }
    } else if (step == 2) {
      if (chooser.picked.length == 1) {
        this.purple[chooser.picked[0].id] = false;
        this.build_crane = chooser.picked[0].builtAt.substr(3);
        this.build_discount = chooser.picked[0].cost;
      }
      this.build(3);
    } else if (step == 3) {
      choices = new Array();
      for (i=0; i<this.buildings.length; i++) {
        if (this.buildings[i].gold) {
          choices.push(this.buildings[i]);
        }
      }
      if (this.purple[CARD_BLACK_MARKET] && (choices.length > 0)) {
        option = Math.min(choices.length, 2);
        chooser.start(choices, option, false, ROLE_BUILDER, 4, "Builder Phase: Select black market goods.");
      } else {
        this.build(5);
      }
    } else if (step == 4) {
      if (chooser.picked.length > 0) {
        for (i=0; i<chooser.picked.length; i++) {
          chooser.picked[i].trade()
          this.build_discount++;
        }
      }
      this.build(5);
    } else if (step == 5) {

      choices = new Array();
      this.build_cantBuild = new Array();
      for (i=0; i<this.hand.length; i++) {
        actual_cost = this.actualCost(this.hand[i]);
        if ((this.build_crane != -1) && this.hand[i].id == this.buildings[this.build_crane].id) {
          this.build_cantBuild.push(this.hand[i]);
        } else if ((actual_cost < this.hand.length) && ((this.hand[i].type == 'p') || !this.purple[this.hand[i].id])) {
          choices.push(this.hand[i]);
        } else {
          this.build_cantBuild.push(this.hand[i]);
        }
      }
      if (choices.length > 0) {
        chooser.start(choices, 1, false, ROLE_BUILDER, 6, "Builder Phase: Select a card to build.");
      } else {
        window.alert("You cannot build anything.");
        if (this.build_crane != -1) {
          this.purple[this.buildings[this.build_crane].id] = true;
        }
        this.build(9);
      }
    } else if (step == 6) {
      if (chooser.picked.length == 1) {
        this.build_new = chooser.picked[0];
        this.hand = chooser.notPicked;
        for (i=0; i<this.build_cantBuild.length; i++) {
          this.hand.push(this.build_cantBuild[i]);
        }
        actual_cost = this.actualCost(this.build_new);
        chooser.start(this.hand, actual_cost, true, ROLE_BUILDER, 7, "Builder Phase: Select card(s) to spend.");
      } else if (this.build_crane != -1) {
        this.purple[this.buildings[this.build_crane].id] = true;
        this.build(9);
      } else {
        this.build(9);
      }
    } else if (step == 7) {
      if (this.build_crane == -1) {
        this.newBuilding(this.build_new);
      } else {
        this.buildOver(this.build_new, this.build_crane);
      }
      this.hand = chooser.notPicked;
      for (i=0; i<chooser.picked.length; i++) {
        deck.discard(chooser.picked[i]);
      }
      this.refreshHand();
      this.build(8);
    } else if (step == 9) {
      if (turn % 2 == this.number) {
        player[1].build(1);
      } else {
        endRound(1);
      }
    }
  }
  this.buildComputer = function(step) {
    var i, p_count, actual_cost;
    var bestP = false, bestV = false;
    var choices = new Array();
    if (step < 5) {
      // AI: Black Market not implemented
      // AI: Crane not implemented
      this.build(5);
    } else if (step == 5) {
      this.build_cantBuild = new Array();
      for (i=0; i<this.hand.length; i++) {
        actual_cost = this.actualCost(this.hand[i]);
        if ((actual_cost < this.hand.length) && ((this.hand[i].type == 'p') || !this.purple[this.hand[i].id])) {
          choices.push(this.hand[i]);
        } else {
          this.build_cantBuild.push(this.hand[i]);
        }
      }
      p_count = 0;
      for (i=0; i<this.buildings.length; i++) {
        if (this.buildings[i].type == 'p') {
          p_count++;
        }
      }
      if (choices.length == 0) {
        this.build(9);
      }
      if (choices.length > 0) {
        for (i=0; i<choices.length; i++) {
          if ((choices[i].type == 'v') && (bestV == false)) {
            bestV = choices[i];
          } else if ((choices[i].type == 'v') && (choices[i].cost > bestV.cost)) {
            this.build_cantBuild.push(bestV);
            bestV = choices[i];
          } else if ((choices[i].type == 'p') && (bestP == false)) {
            bestP = choices[i];
          } else if ((choices[i].type == 'p') && (choices[i].cost > bestP.cost)) {
            this.build_cantBuild.push(bestP);
            bestP = choices[i];
          } else {
            this.build_cantBuild.push(choices[i]);
          }
        }
      }
      if (bestV == false) {
        this.build_new = bestP;
      } else if (bestP == false) {
        this.build_new = bestV;
      } else if (p_count < 4) {
        this.build_new = bestP;
        this.build_cantBuild.push(bestV);
      } else {
        this.build_new = bestV;
        this.build_cantBuild.push(bestV);
      }
      this.hand = this.build_cantBuild;
      actual_cost = this.actualCost(this.build_new);
      this.hand.sort(costCompareFunction);
      while(actual_cost > 0) {
        deck.discard(this.hand.pop());
        actual_cost--;
      }
      this.newBuilding(this.build_new);
      this.build(8);
    } else if (step == 9) {
      if (turn % 2 == this.number) {
        player[0].build(1);
      } else {
        endRound(1);
      }
    }
  }
  this.actualCost = function(card) {
    var p_discount, v_discount, actual_cost;
    p_discount = (turn % 2 == this.number) ? 1 : 0;
    v_discount = (turn % 2 == this.number) ? 1 : 0;
    if ((turn % 2 == this.number) && this.purple[CARD_LIBRARY]) {
      p_discount++;
      v_discount++;
    }
    if (this.purple[CARD_QUARRY]) {
      v_discount++;
    }
    if (this.purple[CARD_SMITHY]) {
      p_discount++;
    }
    actual_cost = card.cost;
    actual_cost -= this.build_discount;
    actual_cost -= (card.type == 'p') ? p_discount : v_discount;
    actual_cost = (actual_cost < 0) ? 0 : actual_cost;
    return actual_cost;
  }



  this.produce = function(step) {
    var ability = (turn % 2 == this.number) ? 2 : 1;
    if ((turn % 2 == this.number) && this.purple[CARD_LIBRARY]) {
      ability += 1;
    }
    if (this.purple[CARD_AQUEDUCT]) {
      ability += 1;
    }
    if (this.type == "human") {
      this.produceHuman(step, ability)
    } else if (this.type == "computer") {
      this.produceComputer(step, ability);
    }
  }
  this.produceHuman = function(step, ability) {
    var i;
    var choices = new Array();
    if (step == 1) {
      for (i=0; i<this.buildings.length; i++) {
        if ((this.buildings[i].type == 'p') && !this.buildings[i].gold) {
          choices.push(this.buildings[i]);
        }
      }
      if (choices.length > 0) {
        ability = Math.min(ability, choices.length);
        chooser.start(choices, ability, false, ROLE_PRODUCER, 2, "Producer Phase: Select building(s) to produce.");
      } else {
        window.alert("You cannot produce.");
        this.produce(3);
      }
    } else if (step == 2) {
      for (i=0; i<chooser.picked.length; i++) {
        chooser.picked[i].produce();
      }
      if (this.purple[CARD_WELL] && (chooser.picked.length >= 2)) {
        this.newCard(deck.draw());
      }
      this.produce(3);
    } else if (step == 3) {
      if (turn % 2 == this.number) {
        player[1].produce(1);
      } else {
        endRound(1);
      }
    }
  }
  this.produceComputer = function(step, ability) {
    var i, produced = 0;
    var bldgs = new Array();
    for (i=0; i<this.buildings.length; i++) {
      if ((this.buildings[i].type == 'p') && !this.buildings[i].gold) {
        bldgs.push(this.buildings[i]);
      }
    }
    bldgs.sort(costCompareFunction);
    for (i=0; i<bldgs.length; i++) {
      if (i < ability) {
        bldgs[i].produce();
        produced++;
      }
    }
    if (this.purple[CARD_WELL] && (produced >= 2)) {
      this.newCard(deck.draw());
    }
    if (turn % 2 == this.number) {
      player[0].produce(1);
    } else {
      endRound(1);
    }
  }



  this.trade = function(step) {
    var ability;
    if (turn % 2 == this.number) {
      rates.start();
    }
    ability = (turn % 2 == this.number) ? 2 : 1;
    if ((turn % 2 == this.number) && this.purple[CARD_LIBRARY]) {
      ability += 1;
    }
    if (this.purple[CARD_TRADING_POST]) {
      ability += 1;
    }
    if (this.type == "human") {
      this.tradeHuman(step, ability)
    } else if (this.type == "computer") {
      this.tradeComputer(step, ability)
    }
  }
  this.tradeHuman = function(step, ability) {
    var i, j, count;
    var choices = new Array();
    if (step == 1) {
      for (i=0; i<this.buildings.length; i++) {
        if (this.buildings[i].gold) {
          choices.push(this.buildings[i]);
        }
      }
      if (choices.length > 0) {
        ability = Math.min(ability, choices.length);
        chooser.start(choices, ability, false, ROLE_TRADER, 2, "Trader Phase: Select goods to trade.");
      } else {
        window.alert("You have nothing to trade.");
        this.trade(3);
      }
    } else if (step == 2) {
      for (i=0; i<chooser.picked.length; i++) {
        chooser.picked[i].trade();
        count = rates.get(chooser.picked[i]);
        for (j=0; j<count; j++) {
          this.newCard(deck.draw());
        }
      }
      if (this.purple[CARD_MARKET_HALL] && (chooser.picked.length >= 1)) {
        this.newCard(deck.draw());
      }
      if (this.purple[CARD_MARKET_STAND] && (chooser.picked.length >= 2)) {
        this.newCard(deck.draw());
      }
      this.trade(3);
    } else if (step == 3) {
      if (turn % 2 == this.number) {
        player[1].trade(1);
      } else {
        rates.end();
        endRound(1);
      }
    }
  }
  this.tradeComputer = function(step, ability) {
    var i, j, count, traded = 0;
    var bldgs = new Array();
    for (i=0; i<this.buildings.length; i++) {
      if ((this.buildings[i].type == 'p') && this.buildings[i].gold) {
        bldgs.push(this.buildings[i]);
      }
    }
    bldgs.sort(costCompareFunction);
    for (i=0; i<bldgs.length; i++) {
      if (i < ability) {
        bldgs[i].trade();
        count = rates.get(bldgs[i]);
        for (j=0; j<count; j++) {
          this.newCard(deck.draw());
        }
        traded++;
      }
    }
    if (this.purple[CARD_MARKET_HALL] && (traded >= 1)) {
      this.newCard(deck.draw());
    }
    if (this.purple[CARD_MARKET_STAND] && (traded >= 2)) {
      this.newCard(deck.draw());
    }
    if (turn % 2 == this.number) {
      player[0].trade(1);
    } else {
      rates.end();
      endRound(1);
    }
  }



  this.prospect = function(step) {
    var cardsToDraw;
    if (step == 1) {
      // Number of cards to draw
      cardsToDraw = (turn % 2 == this.number) ? 1 : 0;
      if ((turn % 2 == this.number) && this.purple[CARD_LIBRARY]) {
        cardsToDraw = cardsToDraw + 1;
      }
      // Draw cards
      for (i=0; i<cardsToDraw; i++) {
        this.newCard(deck.draw());
      }
      this.prospect(2);
    } else if (step > 1) {
      if (this.type == "human") {
        this.prospectHuman(step);
      } else if (this.type == "computer") {
        this.prospectComputer(step);
      }
    }
  }
  this.prospectHuman = function(step) {
    var mine = new Array();
    var playerNumber = this.number + 1;
    if (step == 2) {
      if (this.purple[CARD_GOLD_MINE]) {
        var i, playerNumber;
        var mine = new Array();
        for (var i=0; i<4; i++) {
          mine.push(deck.draw());
        }
        if (allDifferent(mine[0].cost, mine[1].cost, mine[2].cost, mine[3].cost)) {
          history("Player 1 found gold.");
          chooser.start(mine, 1, false, ROLE_PROSPECTOR, 3, "Gold Mine: Select card to keep.");
        } else {
          deck.discard(mine[0]); deck.discard(mine[1]); deck.discard(mine[2]); deck.discard(mine[3]);
          history("Player 1 did not find gold.");
          window.alert("You did not find gold.");
          this.prospect(4);
        }
      } else {
        this.prospect(4);
      }
    } else if (step == 3) {
      this.newCard(chooser.picked[0]);
      deck.discard(chooser.notPicked[0]);
      deck.discard(chooser.notPicked[1]);
      deck.discard(chooser.notPicked[2]);
      this.prospect(4);
    } else if (step == 4) {
      if (turn % 2 == this.number) {
        player[1].prospect(1);
      } else {
        endRound(1);
      }
    }
  }
  this.prospectComputer = function(step) {
    var i;
    var mine = new Array();
    var playerNumber = this.number + 1;
    if (this.purple[CARD_GOLD_MINE]) {
      for (i=0; i<4; i++) {
        mine.push(deck.draw());
      }
      if (allDifferent(mine[0].cost, mine[1].cost, mine[2].cost, mine[3].cost)) {
        this.decideCardToKeep(mine, 1);
        history("Player 2 found gold.");
        window.alert("Player " + playerNumber + " found gold.");
      } else {
        for (i=0; i<mine.length; i++) {
          deck.discard(mine[i]);
        }
        history("Player 2 did not find gold.");
        window.alert("Player " + playerNumber + " did not find gold.");
      }
    }
    if (turn % 2 == this.number) {
      player[0].prospect(1);
    } else {
      endRound(1);
    }
  }



  this.decideCardToKeep = function(choices, numToKeep) {
    var i, bestP, bestV, notChoosen;
    while (numToKeep > 0) {
      bestP = false, bestV = false;
      notChoosen = new Array();
      for (i=0; i<choices.length; i++) {
        if ((choices[i].type == 'v') && this.purple[choices[i].id]) {
          notChoosen.push(choices[i]);
        } else if ((choices[i].type == 'v') && cardMember(choices[i], this.hand)) {
          notChoosen.push(choices[i]);
        } else if ((choices[i].type == 'v') && (bestV == false)) {
          bestV = choices[i];
        } else if ((choices[i].type == 'v') && (choices[i].cost > bestV.cost)) {
          notChoosen.push(bestV);
          bestV = choices[i];
        } else if ((choices[i].type == 'p') && (choices[i].cost >= 3) && (bestP == false)) {
          bestP = choices[i];
        } else if ((choices[i].type == 'p') && (choices[i].cost >= 3) && (choices[i].cost > bestP.cost)) {
          notChoosen.push(bestP);
          bestP = choices[i];
        } else {
          notChoosen.push(choices[i]);
        }
      }
      if ((bestV == false) && (bestP == false)) {
        this.newCard(notChoosen.pop());
      } else if (bestV == false) {
        this.newCard(bestP);
      } else if (bestP == false) {
        this.newCard(bestV);
      } else {
        this.newCard(bestV);
        notChoosen.push(bestP);
      }
      choices = notChoosen;
      numToKeep--;
    }
    for (i=0; i<choices.length; i++) {
      deck.discard(choices[i]);
    }
  }



  this.newCard = function(card) {
    this.hand.push(card);
    this.refreshHand();
  }



  this.newBuilding = function(card) {
    this.purple[card.id] = true;
    card.drawSmallAt("p" + this.number + "b" + this.buildings.length);
    card.builtAt = "p" + this.number + "b" + this.buildings.length;
    this.buildings.push(card);
    this.vp = this.vp + card.vp;
    document.getElementById("p" + this.number + "vp").innerHTML = this.vp;
  }
  this.buildOver = function(card, local) {
    var old_bldg = this.buildings[local];
    this.purple[old_bldg.id] = false;
    this.purple[card.id] = true;
    card.drawSmallAt("p" + this.number + "b" + local);
    card.builtAt = "p" + this.number + "b" + local;
    this.buildings[local] = card;
    this.vp = this.vp + card.vp - old_bldg.vp;
    document.getElementById("p" + this.number + "vp").innerHTML = this.vp;
  }



  this.refreshHand = function() {
    if (this.number == 0) {
      for (var i=0; i<24; i++) {
        if (i < this.hand.length) {
          this.hand[i].drawSmallAt("hand" + i);
        } else {
          document.getElementById("hand" + i).childNodes[0].src = "images/blank.gif";
        }
      }
    }
    document.getElementById("p" + this.number + "cardcount").innerHTML = this.hand.length;
  }



  this.showLarge = function(what, num) {
    if ((what == "bldgs") && (num < this.buildings.length)) {
      this.buildings[num].showLarge();
    } else if ((what == "hand") && (num < this.hand.length)) {
      this.hand[num].showLarge();
    }
  }
  this.hideLarge = function() {
    document.getElementById("largePic").style.visibility = "hidden";
  }

}
