BSG II

In this example below you will see how to do a BSG II with some HTML / CSS and Javascript

Thumbnail
This awesome code was written by ztt628, you can see more from this user in the personal repository.
You can find the original code on Codepen.io
Copyright ztt628 ©
  • HTML
  • CSS
  • JavaScript
    

/*Downloaded from https://www.codeseek.co/ztt628/bsg-ii-yoxEPx */
    


/*Downloaded from https://www.codeseek.co/ztt628/bsg-ii-yoxEPx */
    javascript: (function() {
  var myPlayerNum = 1;
  myPlayerNum--;

  /* import bsg data from quickbar */
  /*TODO: check romo/lampkin with spreadsheet */
  var d = JSON.parse(
    document
      .getElementsByClassName("quickbar_link")[9]
      .getElementsByTagName("a")[0]
      .href.slice(33, -6)
  );

  /* game state, imported from seed. */
  var z = {};
  /* if we need more functions, we can import them from another quickbar */

  var t = document.getElementsByTagName("textarea")[0];

  var myPlayer = "Boxey";
  var myCharacter = -1;
  /*var myCharacter = playerCharacters[myPlayerNum];  */

  /* use eval to slough off code. */
  
    function shuffle(array) {
      for (var i = array.length; i > 0; i--) {
        var rando = Math.floor(Math.random() * i);
        var removed = array.splice(rando, 1)[0];
        array.push(removed);
      }
      return array;
    };
    function colorText(color, text) {
      return "[col" + "or=" + color + "]" + text + "[/color]";
    };
    function size(text, pt) {
      return "[siz" + "e=" + pt + "]" + text + "[/size]";
    };
    function bold(text) {
      return "[b" + "]" + text + "[/b]";
    };
    function spoiler(text) {
      return "[o" + "]" + text + "[/o]";
    };
    function invisible(str) {
      return "[color=" + "#F4F4FF]" + str + "[/" + "color]";
    };
    function strikethrough(text) {
      return "[-" + "]" + text + "[/-]";
    };
    function italics(text) {
      return "[i" + "]" + text + "[/i]";
    };
    function colorIDName(colorID) {
    switch (colorID) {
      case 0:
        return colorText("orange", "Politics");
      case 1:
        return colorText("green", "Leadership");
      case 2:
        return colorText("purple", "Tactics");
      case 3:
        return colorText("red", "Piloting");
      case 4:
        return colorText("blue", "Engineering");
      case 5:
        return colorText("brown", "Treachery");
      default:
        return "Invalid Color ID";
    }
  };
  function cardColorID(id) {
    return Math.floor(id / 35);
  };
  function cardColor(id) {
    switch (Math.floor(id / 35)) {
      case 0:
        return "orange";
      case 1:
        return "green";
      case 2:
        return "purple";
      case 3:
        return "red";
      case 4:
        return "blue";
      case 5:
        return "brown";
      default:
        return "black";
    }
  };
  function cardValue(id) {
    var mod = id % 35;
    if (Math.floor(id / 35) === 5) {
      if (z.daybreak) {
        if (mod >= 23) {
          return 5;
        } else if (mod >= 20) {
          return 4;
        } else if (mod >= 12) {
          return 3;
        } else {
          return 0;
        }
      } else if (z.pegasus) {
        if (mod >= 20) {
          return 3;
        } else if (mod >= 12) {
          return 2;
        } else {
          return 1;
        }
      }
    }

    switch (mod) {
      case 34:
      case 25:
      case 20:
        return 5;
      case 33:
      case 24:
        return 4;
      case 32:
      case 23:
        return 3;
      case 31:
      case 30:
      case 28:
      case 27:
      case 26:
        return 0;
      case 29:
        return 6;
      case 22:
        return 2;
      case 21:
        return 1;
      default:
        if (mod >= 18) {
          return 4;
        } else if (mod >= 14) {
          return 3;
        } else if (mod >= 8) {
          return 2;
        } else if (mod >= 0) {
          return 1;
        } else {
          return -1;
        }
    }
  };
  function cardName(id) {
    var mod = id % 35;
    switch (Math.floor(id / 35)) {
      case 5:
        if (z.daybreak) {
          if (mod >= 23) {
            return "Exploit Weakness";
          } else if (mod >= 20) {
            return "Violent Outbursts";
          } else if (mod >= 16) {
            return "A Better Machine";
          } else if (mod >= 12) {
            return "Personal Vices";
          } else if (mod >= 6) {
            return "Dradis Contact";
          } else {
            return "Bait";
          }
        } else if (z.pegasus) {
          if (mod >= 24) {
            return "Human Weakness";
          } else if (mod >= 20) {
            return "Sabotage";
          } else if (mod >= 17) {
            return "God's Plan";
          } else if (mod >= 12) {
            return "Special Destiny";
          } else if (mod >= 8) {
            return "By Your Command";
          } else {
            return "Broadcast Location";
          }
        }
      case 0:
        if (mod === 34) {
          return "Negotiations";
        } else if (mod >= 32) {
          return "Popular Influence";
        } else if (mod >= 30) {
          return "Force Their Hand";
        } else if (mod === 29) {
          return "Political Prowess";
        } else if (mod >= 26) {
          return "Red Tape";
        } else if (mod >= 23) {
          return "Preventative Policy";
        } else if (mod >= 21) {
          return "Support the People";
        } else if (mod >= 14) {
          return "Investigative Committee";
        } else {
          return "Consolidate Power";
        }
      case 1:
        if (mod === 34) {
          return "Change of Plans";
        } else if (mod >= 32) {
          return "Restore Order";
        } else if (mod >= 30) {
          return "All Hands On Deck";
        } else if (mod === 29) {
          return "State of Emergency";
        } else if (mod >= 26) {
          return "Iron Will";
        } else if (mod >= 23) {
          return "At Any Cost";
        } else if (mod >= 21) {
          return "Major Victory";
        } else if (mod >= 14) {
          return "Declare Emergency";
        } else {
          return "Executive Order";
        }
      case 2:
        if (mod === 34) {
          return "A Second Chance";
        } else if (mod >= 32) {
          return "Unorthodox Plan";
        } else if (mod >= 30) {
          return "Quick Thinking";
        } else if (mod === 29) {
          return "Scout for Fuel";
        } else if (mod >= 26) {
          return "Trust Instincts";
        } else if (mod >= 23) {
          return "Critical Situation";
        } else if (mod >= 21) {
          return "Guts and Initiative";
        } else if (mod >= 14) {
          return "Strategic Planning";
        } else {
          return "Launch Scout";
        }
      case 3:
        if (mod === 34) {
          return "Launch Reserves";
        } else if (mod >= 32) {
          return "Combat Veteran";
        } else if (mod >= 30) {
          return "Dogfight";
        } else if (mod === 29) {
          return "Best of the Best";
        } else if (mod >= 26) {
          return "Dogfight";
        } else if (mod >= 23) {
          return "Run Interference";
        } else if (mod >= 21) {
          return "Full Throttle";
        } else if (mod >= 14) {
          return "Maximum Firepower";
        } else {
          return "Evasive Maneuvers";
        }
      case 4:
        if (mod === 34) {
          return "Test the Limits";
        } else if (mod >= 32) {
          return "Raptor Specialist";
        } else if (mod >= 30) {
          return "Install Upgrades";
        } else if (mod === 29) {
          return "Build Nuke";
        } else if (mod >= 26) {
          return "Establish Network";
        } else if (mod >= 23) {
          return "Calculations";
        } else if (mod >= 21) {
          return "Jury Rigged";
        } else if (mod >= 14) {
          return "Scientific Research";
        } else {
          return "Repair";
        }
      default:
        return "No such card.";
    }
  };
  function cardText(id) {
    var text = "";
    return colorText(cardColor(id), cardValue(id) + " - " + cardName(id));
  }
  function drawFromDeck(colorID) {
    var card = z.skillCardDecks[colorID].pop();
    if (z.skillCardDecks[colorID].length === 0) {
      z.skillCardDecks[colorID] = z.skillCardDiscards[colorID];
      shuffle(z.skillCardDecks[colorID]);
      t.value += colorIDName(colorID) + " deck empty; reshuffling.\r\n";
      z.skillCardDiscards[colorID] = [];
    }
    /* will return undefined if empty */
    return card;
  }
  function buildDestiny() {
    t.value += "Destiny rebuilt.\r\n";

    if (z.destiny.length != 0) {
      alert("Cannot rebuild Destiny; Destiny not empty.");
      return 0;
    }
    for (var colorID = 0; !(colorID >= z.skillCardDecks.length); colorID++) {
      for (var i = 2; i > 0; i--) {
        var card = drawFromDeck(colorID);
        if (card !== undefined) {
          z.destiny.push(card);
        } else {
          t.value +=
            "Note: there are no cards in the " +
            colorIDName(colorID) +
            " deck or its discards; Destiny now has fewer cards than usual.\r\n";
        }
      }
    }
    shuffle(z.destiny);
  }
  function playDestinyToSkillCheck() {
    if (z.destiny.length === 0) {
      alert("Destiny is empty and cannot be rebuilt.");
      return 0;
    }
    t.value += "Playing Destiny into the skill check.\r\n";
    z.skillCheckCards[z.numPlayers].push(z.destiny.pop());
    if (destiny.length === 0) {
      buildDestiny();
    }
    z.skillCheckCards[z.numPlayers].push(z.destiny.pop());
    if (destiny.length === 0) {
      buildDestiny();
    }
  }
  function dealSkillCard(player, colorID) {
    var card = drawFromDeck(colorID);
    z.possibleColors[player][colorID] = 1;
    if (card !== undefined) {
      z.skillCardHands[player].push(card);
      t.value +=
        bold(
          z.players[player] + " draws a " + colorIDName(colorID) + " card."
        ) + "\r\n";
    } else {
      t.value +=
        "Attempted to deal a " +
        colorIDName(colorID) +
        " card to " +
        z.players[player] +
        ", but could not as that deck and its discards are depleted.\r\n";
    }
  }
  function dealQuorumCard() {
    if (z.quorumDeck.length === 0) {
      t.value +=
        "You have completely exhausted the Quorum deck and its discards and cannot draw more Quorums.\r\n";
      return 0;
    }
    var card = z.quorumDeck.pop();
    if (z.quorumDeck.length === 0) {
      z.quorumDeck = z.quorumDiscards;
      shuffle(z.quorumDeck);
      t.value += "Quorum deck empty; reshuffling.\r\n";
      z.quorumDiscards = [];
    }
    z.quorumHand.push(card);
    t.value +=
      "President " + z.players[z.president] + " draws a Quorum card.\r\n";
  }
  /* Issue: rebuilding decks when completely empty.  Have manual option to do this, don't check for it. */
  /* TODO: have this as option */
  function emptyDeckChecker() {
    for (var i = 0; !(i >= z.skillCardDecks.length); i++) {
      if (
        z.skillCardDecks[i].length === 0 &&
        z.skillCardDiscards[i].length !== 0
      ) {
        z.skillCardDecks[i] = z.skillCardDiscards[i];
        shuffle(z.skillCardDecks[i]);
        z.skillCardDiscards[i] = [];
      }
    }
    if (z.quorumDeck.length === 0 && z.quorumDiscards.length !== 0) {
      z.quorumDeck = z.quorumDiscards;
      shuffle(z.quorumDeck);
      z.quorumDiscards = [];
    }
    if (z.crisisDeck.length === 0 && z.crisisDiscards.length !== 0) {
      z.crisisDeck = z.crisisDiscards;
      shuffle(z.crisisDeck);
      z.crisisDiscards = [];
    }
  }
  function discardSkillCard(player, pos) {
    if (!(pos >= 0) || pos >= z.skillCardHands[player].length) {
      alert("Cannot discard a card you do not have in hand!");
      return 0;
    }
    var card = z.skillCardHands[player].splice(pos, 1)[0];
    z.skillCardDiscards[cardColorID(card)].push(card);
    t.value +=
      bold(z.players[player] + " discards " + cardText(card)) + ".\r\n";
    if (z.skillCardHands[player].length === 0) {
      z.possibleColors[player] = [0, 0, 0, 0, 0];
      if (z.pegasus || z.daybreak) {
        z.possibleColors[player].push(0);
      }
    }
  }
  /* Returns the card id discarded. */
  function discardRandomSkillCard(player) {
    if (z.skillCardHands[player].length > 0) {
      var card = z.skillCardHands[player].splice(
        Math.floor(Math.random() * z.skillCardHands[player].length),
        1
      )[0];
      z.skillCardDiscards[cardColorID(card)].push(card);
      t.value +=
        z.players[player] + " discards " + cardText(card) + " randomly.\r\n";
      if (z.skillCardHands[player].length === 0) {
        z.possibleColors[player] = [0, 0, 0, 0, 0];
        if (z.pegasus || z.daybreak) {
          z.possibleColors[player].push(0);
        }
      }
      return card;
    } else {
      t.value +=
        "ERROR: " +
        z.players[player] +
        " has no skill cards to discard, randomly or otherwise.\r\n";
      return -1;
    }
  }
  function playSkillCard(player, pos) {
    if (!(pos >= 0) || pos >= z.skillCardHands[player].length) {
      alert("Cannot play a card you do not have in hand!");
      return 0;
    }
    var card = z.skillCardHands[player].splice(pos, 1)[0];
    z.skillCardDiscards[cardColorID(card)].push(card);
    t.value += z.players[player] + " plays " + cardText(card) + ".\r\n";
    /* need response for each card. */
  }
  function playCardToSkillCheck(player, pos) {
    if (!(pos >= 0) || pos >= z.skillCardHands[player].length) {
      alert("Cannot play into skill check a card you do not have in hand!");
      return 0;
    }
    var card = z.skillCardHands[player].splice(pos, 1)[0];
    z.skillCheckCards[player].push(card);
    t.value += z.players[player] + " plays a card into the skill check.\r\n";
    /* need IC handling */
  }
  function isCylonLeader(x) {
    /* Note: does not include Sympathetic Cylon */
    return (
      x === "Cavil" ||
      x === "Leoben" ||
      x === "Six" ||
      x === "Doral" ||
      x === "Simon" ||
      x === "Athena" ||
      x === "D'Anna"
    );
  }
  function getCharacter(name) {
    for (var i = 0; !(i >= d.characters.length); i++) {
      if (d.characters[i] === name) {
        return i;
      }
    }
    return -1;
  }
  /* Takes old rank */
  function passPresident(old) {
    var best = 99;
    /* pass accept prophecy */
    var prophet = -1;
    for (
      var i = 0;
      z.president >= 0 && !(i >= z.quorumTitles[z.president].length);
      i++
    ) {
      if (z.quorumTitles[z.president][i] === 0) {
        prophet = i;
      }
    }
    for (var i = 0; !(i >= z.numPlayers); i++) {
      var character = getCharacter(z.players[i]);
      var rank = d.presidentSuccession[character];
      if (!(rank >= best) && z.revealedCylons[i] === 0 && rank !== old) {
        if (prophet !== -1) {
          z.quorumTitles[i] = z.quorumTitles[i].concat(
            z.quorumTitles[z.president].splice(prophet)
          );
        }
        z.president = i;
        best = rank;
      }
    }
  }
  function passAdmiral(old) {
    var best = 99;
    for (var i = 0; !(i >= z.numPlayers); i++) {
      var character = getCharacter(z.players[i]);
      var rank = d.admiralSuccession[character];
      if (
        !(rank >= best) &&
        z.revealedCylons[i] === 0 &&
        rank !== old &&
        z.playerLocations[i] !== "Brig"
      ) {
        z.admiral = i;
        best = rank;
      }
    }
  }
  function passCAG(old) {
    var best = 99;
    for (var i = 0; !(i >= z.numPlayers); i++) {
      var character = getCharacter(z.players[i]);
      var rank = d.cagSuccession[character];
      if (
        !(rank >= best) &&
        z.revealedCylons[i] === 0 &&
        rank !== old &&
        z.playerLocations[i] !== "Brig"
      ) {
        z.cag = i;
        best = rank;
      }
    }
  }
  function getDistance(destinationID) {
    switch (destinationID) {
      case 0:
      case 1:
      case 6:
      case 11:
      case 22:
      case 28:
      case 32:
        return 3;
      case 2:
      case 3:
      case 4:
      case 5:
      case 7:
      case 8:
      case 9:
      case 10:
      case 15:
      case 16:
      case 17:
      case 23:
      case 25:
      case 29:
      case 30:
      case 33:
      case "The Search for Home":
        return 2;
      case 12:
      case 13:
      case 14:
      case 18:
      case 19:
      case 20:
      case 21:
      case 24:
      case 27:
      case 31:
      case "Legendary Discovery":
      case "Digging up the Past":
        return 1;
      case 26:
        return 0;
      default:
        return 0;
    }
  }
  function parseLocation(location) {
    /*TODO: this.  may also want to strip apostrophes */
    location = location.toLowerCase();
    switch (location) {
      case "ftl":
      case "ftl control":
      case "gaeta":
        return "FTL Control";
      case "weapons control":
      case "weapons":
      case "hot dog":
      case "kendra":
      case "shaw":
      case "helo":
      case "karl":
      case "racetrack":
        return "Weapons Control";
      case "command":
      case "galactica cic":
      case "cain":
      case "kelly":
      case "tigh":
        return "Command";
      case "communications":
      case "comms":
      case "hoshi":
      case "dee":
      case "leoben":
        return "Communications";
      case "research lab":
      case "research":
      case "lab":
      case "cavil":
      case "baltar":
      case "gaius":
        return "Research Lab";
      case "admiral's quarters":
      case "aq":
      case "admirals Quarters":
      case "admiral's":
      case "ellen":
      case "adama":
        return "Admiral's Quarters";
      case "hangar deck":
      case "hangar":
      case "deck":
      case "starbuck":
      case "cally":
      case "chief":
      case "kat":
      case "apollo":
      case "lee":
        return "Hangar Deck";
      case "armory":
      case "armoury":
      case "anders":
      case "crashdown":
      case "boomer":
      case "seelix":
      case "hardball":
        return "Armory";
      case "sickbay":
        return "Sickbay";
      case "brig":
        return "Brig";
      case "airlock":
        return "Airlock";
      case "caprica":
        return "Caprica";
      case "detention":
        return "Detention";
      case "shipyard":
        return "Shipyard";
      case "raider bay":
        return "Raider Bay";
      case "hybrid tank":
        return "Hybrid Tank";
      case "datasream":
        return "Datastream";
      case "hub destroyed":
        return "Hub Destroyed";
      case "stranded on caprica":
        return "Stranded on Caprica";
      case "administration":
      case "admin":
      case "zarek":
      case "tom":
      case "doral":
      case "billy":
      case "keikeya":
        return "Administration";
      case "president's office":
      case "presidents office":
      case "president's":
      case "roslin":
      case "elosha":
        return "President's Office";
      case "press room":
      case "press":
      case "tory":
      case "d'anna":
        return "Press Room";
      case "quorum chamber":
      case "quorum":
      case "chamber":
        return "Quorum Chamber";
      case "pegasus cic":
      case "cic":
        return "Pegasus CIC";
      case "main batteries":
      case "mb":
      case "batteries":
        return "Main Batteries";
      case "engine room":
      case "engine":
        return "Engine Room";
      case "resurrection ship":
      case "resurrection":
        return "Resurrection Ship";
      case "human fleet":
      case "human":
        return "Human Fleet";
      case "cylon fleet":
      case "cylon":
        return "Cylon Fleet";
      case "basestar bridge":
      case "basestar":
        return "Basestar Bridge";
      case "medical center":
      case "medical centre":
      case "medical":
        return "Medical Center";
      case "resistance hq":
      case "rhq":
      case "resistance":
      case "hq":
        return "Resistance HQ";
      case "occupation authority":
      case "authority":
      case "occupation":
      case "oa":
        return "Occupation Authority";
      case "breeder's canyon":
      case "breeders canyon":
      case "breeders' canyon":
      case "breeder's":
      case "canyon":
        return "Breeder's Canyon";
      case "bridge":
      case "demetrius bridge":
        return "Bridge";
      case "tactical plot":
      case "tactical":
      case "plot":
        return "Tactical Plot";
      case "captain's cabin":
      case "captains cabin":
      case "captains' cabin":
      case "cabin":
      case "captain's":
      case "cc":
        return "Captain's Cabin";
      default:
        return "NONE";
    }
  }
  function isOnNewCaprica(player) {
    var playerLocation = z.playerLocations[player];
    return (
      playerLocation === "Detention" ||
      playerLocation === "Medical Center" ||
      playerLocation === "Resistance HQ" ||
      playerLocation === "Occupation Authority" ||
      playerLocation === "Breeder's Canyon" ||
      playerLocation === "Shipyard"
    );
  }
  /* tests if it is a valid location for the player to move to. Includes Brig/Detention escape restrictions..*/
  function validLocation(player, location) {
    var playerLocation = z.playerLocations[player];
    /* Galactica Locations (not hazardous). */
    if (
      !z.galacticaAway &&
      z.revealedCylons[player] === 0 &&
      playerLocation !== "Detention"
    ) {
      switch (location) {
        case "FTL Control":
        case "Weapons Control":
        case "Communications":
        case "Research Lab":
        case "Command":
        case "Admiral's Quarters":
        case "Hangar Deck":
        case "Armory":
          return true;
      }
    }
    /* Sickbay */
    if (z.revealedCylons[player] === 0 && !isOnNewCaprica(player)) {
      if (location === "Sickbay" || location === "Brig") {
        return true;
      }
    }
    /* Medical Center.  Cylons sent here by execution/deinfiltration only (handled separately) */
    if (isOnNewCaprica(player) && z.revealedCylons[player] === 0) {
      if (location === "Medical Center" || location === "Detention") {
        return true;
      }
    }
    /* Colonial One Locations */
    if (
      !z.galacticaAway &&
      !z.galacticaReturned &&
      !z.colonialOneDestroyed &&
      z.revealedCylons[player] === 0 &&
      z.playerLocations[player] !== "Brig"
    ) {
      switch (location) {
        case "Administration":
        case "President's Office":
        case "Press Room":
          return true;
        case "Quorum Chamber":
          if (z.daybreak) {
            return true;
          } else {
            return false;
          }
      }
    }
    /* Pegasus Locations */
    if (
      z.pegasus &&
      !z.galacticaAway &&
      z.revealedCylons[player] === 0 &&
      locations[player] !== "Brig" &&
      locations[player] !== "Detention" &&
      !z.pegasusDestroyed
    ) {
      switch (location) {
        case "Pegasus CIC":
        case "Airlock":
        case "Main Batteries":
        case "Engine Room":
          return true;
      }
    }
    /* Demetrius */
    if (
      z.destination === "Earth" &&
      z.revealedCylons[player] === 0 &&
      z.locations[player] !== "Brig"
    ) {
      switch (location) {
        case "Bridge":
        case "Tactical Plot":
        case "Captain's Cabin":
          return true;
      }
    }
    /* Cylon Locations (non-hazardous) */
    if (z.revealedCylons[player] === 1 && !z.galacticaAway) {
      switch (location) {
        case "Human Fleet":
        case "Cylon Fleet":
        case "Caprica":
          return true;
      }
    }
    /* Resurrection Ship (moved there [or Hub Destroyed] auto by revealing / de-infiltrating)*/
    if (z.revealedCylons[player] === 1 && !z.pegasus && !z.daybreak) {
      if (location === "Resurrection Ship") {
        return true;
      }
    }
    if (z.revealedCylons[player] === 1 && z.CFB && !z.galacticaAway) {
      if (location === "Basestar Bridge") {
        return true;
      }
    }
    /* Rebel Basestar */
    if (
      (z.rebelBasestar === -1 &&
        z.revealedCylons[player] === 1 &&
        !z.galacticaAway) ||
      (z.rebelBasestar === 1 &&
        z.revealedCylons[player] === 0 &&
        !z.galacticaAway &&
        location[player] !== "Brig" &&
        location[player] !== "Detention")
    ) {
      switch (location) {
        case "Datastream":
        case "Raider Bay":
        case "Hybrid Tank":
          return true;
      }
    }
    if ((z.galacticaAway || z.galacticaReturned) && playerLocation !== "Brig") {
      switch (location) {
        case "Resistance HQ":
        case "Occupation Authority":
        case "Breeder's Canyon":
        case "Shipyard":
          return true;
      }
    }

    return false;
  }
  function movePlayer(player, location) {
    z.playerLocations[player] = location;
    t.value += bold(z.players[player] + " moves to " + location + ".\r\n");
  }
  /* Does not include executions */
  function revealAsCylon() {
    z.playerLocations[myPlayer] = "Resurrection Ship";
    /* TODO: the rest of this. */
  }
  /* for current crisis if no args, crisis x if not */
  function difficultyTemplate() {
    if (arguments.length === 0) {
      var text = "";
      /* TODO: NC Crises, Missions */
      if (
        z.currentSkillCheck === "Airlock" ||
        z.currentSkillCheck === "Brig" ||
        z.currentSkillCheck === "Administration" ||
        z.currentSkillCheck === "Admiral's Quarters" ||
        z.currentSkillCheck === "Resistance HQ" ||
        z.currentSkillCheck === "Detention"
      ) {
        text = z.currentSkillCheck;
      } else if (z.currentSkillCheck >= 0) {
        text = d.crisisNames[z.currentSkillCheck];
      } else {
        return "";
      }
      text += " - " + z.thisDifficulty;
      if (z.thisPartial > 0) {
        text += "(" + z.thisPartial + ")";
      } else if (z.thisConsequence > 0) {
        text += "(*)";
      }
      if (z.thisPolitics > 0) {
        text += colorText("orange", "Y");
      }
      if (z.thisLeadership > 0) {
        text += colorText("green", "G");
      }
      if (z.thisTactics > 0) {
        text += colorText("purple", "P");
      }
      if (z.thisPiloting > 0) {
        text += colorText("red", "R");
      }
      if (z.thisEngineering > 0) {
        text += colorText("blue", "B");
      }
      if (z.thisTreachery > 0) {
        text += colorText("brown", "O");
      }
      return bold(text);
    } else {
      var x = arguments[0];
      var text = d.crisisNames[x];
      if (
        d.CAC[x] === 0 &&
        d.admiralChooses[x] === 0 &&
        d.presidentChooses[x] === 0 &&
        d.cagChooses[x] === 0
      ) {
        text += " - " + d.difficulty[x];
        if (d.partial[x] > 0) {
          text += "(" + d.partial[x] + ")";
        } else if (d.consequence[x] > 0) {
          text += "(*)";
        }
        if (d.positives[0][x] > 0) {
          text += colorText("orange", "Y");
        }
        if (d.positives[1][x] > 0) {
          text += colorText("green", "G");
        }
        if (d.positives[2][x] > 0) {
          text += colorText("purple", "P");
        }
        if (d.positives[3][x] > 0) {
          text += colorText("red", "R");
        }
        if (d.positives[4][x] > 0) {
          text += colorText("blue", "B");
        }
      }
      return bold(text);
    }
  }
  /* To do: Calc CO? */
  function SPToken(eventName) {
    var text = '[q="Interrupts for ' + eventName + '"]\r\n';
    text += bold(size("Interrupts for " + eventName, 14)) + "\r\n";
    text +=
      "Looking for " + colorText("purple", "Strategic Planning") + ".\r\n\r\n";
    for (var i = z.currentPlayer; !(i >= z.currentPlayer + z.numPlayers); i++) {
      var interruptPlayer = i % z.numPlayers;
      text +=
        z.players[interruptPlayer] +
        " (" +
        z.skillCardHands[interruptPlayer].length +
        ") - ";
      if (z.skillCardHands[interruptPlayer].length === 0) {
        text += "PASS: No Cards";
      } else if (z.revealedCylons[interruptPlayer] === 1) {
        text += "PASS: Cylon";
      } else if (z.possibleColors[interruptPlayer][2] === 0) {
        text += "PASS: No Tactics";
      } else {
        /* TODO: SP play into token? Can we use interrupts?  Need to discard interrupts once skill check starts in case fail result is die roll (bomb threat) */
      }
      text += "\r\n";
    }
    /* TODO: certain Conditional Orders */
    text += "[/q]\r\n";

    t.value += text;
  }
  /* TODO: Pass: no Politics or Engineering, etc. */
  function interruptsToken() {
    var text =
      '[q="Interrupts for ' + d.crisisNames[z.currentCrisis] + '"]\r\n';
    text += size(difficultyTemplate(), 14) + "\r\n";
    var interruptPossibilities = [];
    if (!z.investigativeCommittee) {
      interruptPossibilities.push(
        colorText("orange", "Investigative Committee")
      );
    }
    if (!z.thisEngineering) {
      interruptPossibilities.push(colorText("blue", "Scientific Research"));
    }
    /* TODO: Second Chance fun.  AVP makes this difficult. */
    if (z.daybreak) {
      interruptPossibilities.push(colorText("purple", "A Second Chance"));
      if (!z.pegasus) {
        interruptPossibilities.push(colorText("green", "Restore Order"));
      } else {
        var recklessText = "ONE of the following: ";
        if (!z.thisTreachery) {
          recklessText += colorText("green", "At Any Cost") + ", ";
        }
        recklessText +=
          colorText("orange", "Support the People") +
          ", " +
          colorText("blue", "Jury Rigged") +
          ", ";
        if (z.daybreak) {
          recklessText +=
            colorText("purple", "Guts and Initative") +
            ", or " +
            colorText("green", "Restore Order");
        } else {
          recklessText += "or " + colorText("purple", "Guts and Initiative");
        }
        interruptPossibilities.push(recklessText);
      }
    }
    if (interruptPossibilities.length > 0) {
      text += "Looking for ";
      for (var i = 0; !(i >= interruptPossibilities.length); i++) {
        if (i === interruptPossibilities.length - 1 && i !== 0) {
          text += "and/or ";
        }
        text += interruptPossibilities[i];
        if (i === interruptPossibilities.length - 1) {
          text += ".\r\n\r\n";
        } else {
          text += ",\r\n";
        }
      }
    }
    /* TODO: rare interrupts? */
    /* TODO: include played interrupts (text only) */
    for (var i = z.currentPlayer; !(i >= z.currentPlayer + z.numPlayers); i++) {
      var interruptPlayer = i % z.numPlayers;
      text +=
        z.players[interruptPlayer] +
        " (" +
        z.skillCardHands[interruptPlayer].length +
        ") - ";
      if (z.skillCardHands[interruptPlayer].length === 0) {
        text += "PASS: No Cards";
      } else if (z.revealedCylons[interruptPlayer] === 1) {
        text += "PASS: Cylon";
      } else {
        if (z.interrupts[interruptPlayer].length > 0) {
          for (var j = 0; !(j >= z.interrupts[interruptPlayer].length); j++) {
            text += z.interrupts[interruptPlayer][j];
            if (j !== z.interrupts[interruptPlayer].length - 1) {
              text += ", ";
            }
          }
        }
      }
      text += "\r\n";
    }
    /* TODO: certain Conditional Orders */
    text += "[/q]\r\n";

    t.value += text;
  }
  function startCrisisSkillCheck() {
    if (z.currentCrisis === null) {
      return null;
    }
    z.currentSkillCheck = z.currentCrisis;
    z.thisDifficulty = d.difficulty[z.currentCrisis];
    z.thisPartial = d.partial[z.currentCrisis];
    z.thisConsequence = d.consequence[z.currentCrisis];
    z.thisPolitics = d.positives[0][z.currentCrisis];
    z.thisLeadership = d.positives[1][z.currentCrisis];
    z.thisTactics = d.positives[2][z.currentCrisis];
    z.thisPiloting = d.positives[3][z.currentCrisis];
    z.thisEngineering = d.positives[4][z.currentCrisis];
    z.thisTreachery = 0;
    return null;
  }
  function playCrisis() {
    z.currentCrisis = z.crisisDeck.pop();
    if (d.CAC[z.currentCrisis]) {
      t.value += "[ima" + "geid=647924 medium]\r\n";
      t.value +=
        size(
          colorText("red", italics(bold(d.crisisNames[z.currentCrisis]))),
          14
        ) + "\r\n";
      /* TODO: CACS */
    } else {
      t.value += "[ima" + "geid=735196 medium]\r\n";
      t.value +=
        size(italics(difficultyTemplate(z.currentCrisis)), 14) + "\r\n";
      if (d.admiralChooses[z.currentCrisis]) {
        t.value +=
          bold(colorText("green", "Admiral") + " " + z.players[z.admiral]) +
          ", your choice here.\r\n";
      } else if (d.presidentChooses[z.currentCrisis]) {
        t.value +=
          bold(
            colorText("orange", "President") + " " + z.players[z.president]
          ) + ", your choice here.\r\n";
      } else if (d.cagChooses[z.currentCrisis]) {
        t.value +=
          bold(colorText("red", "CAG") + " " + z.players[z.cag]) +
          ", your choice here.\r\n";
      } else if (d.currentPlayerChooses[z.currentCrisis]) {
        /* TODO: Cancel skill check option for Helo OPG, political prowess, etc. */
        if (z.players[z.currentPlayer] === "Tory") {
          t.value += bold("Tory automatically chooses the top option.");
          startCrisisSkillCheck();
        }
        t.value += bold(z.players[z.currentPlayer]) + ", your choice here.\r\n";
      } else {
        startCrisisSkillCheck();
      }
    }
  }
  function sleeper() {
    t.value += "[ima" + "geid=606443 medium]\r\n";
    t.value = "Entering Sleeper Phase; dealing new Loyalties.\r\n";
    for (var i = 0; !(i >= z.players.length); i++) {
      if (!isCylonLeader(z.players[i])) {
        z.loyaltyHands[i].push(z.loyaltyDeck.pop());
        /*TODO: Sympathizer, Sympathetic Cylon, Mutineer handling */
      } else if (z.daybreak) {
        z.loyaltyHands[i].push(z.motiveDeck.pop());
        z.loyaltyHands[i].push(z.motiveDeck.pop());
      }
      if (z.players[i] === "Boomer") {
        z.loyaltyHands[i].push(z.loyaltyDeck.pop());
        z.playerLocations[i] = "Brig";
        t.value = "Boomer is sent to the Brig.\r\n";
      }
    }
  }
  /* TODO: Check for character boxing. */
  function characterPresent(name) {
    for (var i = 0; !(i >= z.players.length); i++) {
      if (z.players[i] === name) {
        return true;
      }
    }
    return false;
  }
  function getPlayerNum(name){
    for (var i = 0; !(i >= z.players.length); i++) {
      if (z.players[i] === name) {
        return i;
      }
    }
    return -1;
  }
  function startLocationSkillCheck(location, target) {
    z.thisTarget = target;
    z.currentSkillCheck = location;
    z.thisConsequence = 0;
    z.thisPiloting = 0;
    z.thisEngineering = 0;
    if (location === "Admiral's Quarters") {
      z.thisDifficulty = 7;
      if (z.players[target] === "Starbuck") {
        z.thisDifficulty -= 3;
        t.value += "Difficulty is reduced by 3 due to Starbuck's Insubordinate.\r\n";
      }
      if (characterPresent("Cain")) {
        z.partial = 10;
        t.value += "The partial represents the threshold for Cain's Intolerant ability.\r\n";
      }
      z.thisPolitics = 0;
      z.thisLeadership = 1;
      z.thisTactics = 1;
      z.thisTreachery = 0;
    } else if (location === "Brig") {
      z.thisDifficulty = 7;
      z.thisPolitics = 1;
      z.thisLeadership = 0;
      z.thisTactics = 1;
      z.thisTreachery = 0;
    } else if (location === "Administration") {
      z.thisDifficulty = 5;
      z.thisPolitics = 1;
      z.thisLeadership = 1;
      z.thisTactics = 0;
      z.thisTreachery = 0;
    } else if (location === "Airlock") {
      z.thisDifficulty = 12;
      z.thisPolitics = 1;
      z.thisLeadership = 0;
      z.thisTactics = 1;
      z.thisTreachery = 1;
      /* TODO: check this later in the crisis (e.g. after exploit weakness) */
      if (z.playerLocations[target] === "Brig") {
        t.value += "Difficulty is reduced by 4 as "+z.players[target]+" is in the Brig.\r\n";
        z.difficulty -= 4;
      }
    }
    interruptsToken();
  }
  function isMale(player) {
    switch (z.players[player]) {
      case "Roslin":
      case "Starbuck":
      case "Boomer":
      case "Cain":
      case "Ellen":
      case "Kat":
      case "Dee":
      case "Six":
      case "Tory":
      case "Cally":
      case "D'Anna":
      case "Athena":
        return false;
      default:
        return true;
    }
  }
  function titleList(player) {
    var text = "";
    if (player === z.admiral && player === z.president) {
      if (player === z.cag) {
        if (isMale(player)) {
          text += colorText("purple", "God-King ");
        } else {
          text += colorText("purple", "God-Queen ");
        }
      } else {
        text += colorText("purple", "Dictator ");
      }
    } else {
      if (player === z.admiral) {
        text += colorText("green", "Admiral ");
      } else if (player === z.president) {
        text += colorText("orange", "President ");
      }
      if (player === z.cag) {
        text += colorText("red", "CAG ");
      }
      if (player === z.theMutineer) {
        text += colorText("brown", "Mutineer ");
      }
      for (var i = 0; !(i >= z.quorumTitles[player].length); i++) {
        switch (z.quorumTitles[player][i]) {
          case 0:
            text += colorText("orange", "Prophet ");
            break;
          case 3:
            text += colorText("orange", "Arbitrator ");
            break;
          case 4:
            text += colorText("orange", "Mission Specialist ");
            break;
          case 5:
            text += colorText("orange", "Vice President ");
            break;
          case 17:
            text += colorText("orange", "Chief of Staff ");
            break;
          case 22:
            text += colorText("orange", "Probationer ");
        }
      }
      if (player === z.theCylonLeader && z.revealedCylons[myPlayerNum] === 0) {
        text += colorText("magenta", "Infiltrator ");
      }
    }
    return text;
  }
  function parseCharacter2(char) {
    char = char.toLowerCase();
    switch (char) {
      case "adama":
      case "william adama":
      case "bill adama":
      case "bill":
      case "husker":
      case 'william "husker" adama':
      case "old man":
        return "Adama";
      case "tigh":
      case "saul tigh":
      case "saul":
        return "Tigh";
      case "helo":
      case 'karl "helo" agathon':
      case "military helo":
      case "agathon":
      case 'karl "helo" agathon (original version, military leader)':
        return "Helo";
      case "karl":
      case "pilot helo":
      case 'karl "helo" agathon (alternate version, pilot)':
        return "Karl";
      case "roslin":
      case "laura":
      case "laura roslin":
        return "Roslin";
      case "baltar":
      case "gaius baltar":
      case "gaius baltar (original version, political leader)":
      case "political baltar":
      case "political gaius":
        return "Baltar";
      case "gaius":
      case "gaius baltar (alternate version, support)":
      case "cultar":
      case "trolltar":
        return "Gaius";
      case "tom zarek":
      case "zarek":
      case "political zarek":
      case "tom zarek (original version, political leader)":
        return "Zarek";
      case "tom":
      case "military zarek":
      case "tom zarek (alternate version, military leader)":
        return "Tom";
      case "apollo":
      case 'lee "apollo" adama':
      case 'lee "apollo" adama (original version, pilot)':
      case "pilot lee":
        return "Apollo";
      case "lee":
      case "political lee":
      case "lee adama (alternate version, political leader)":
        return "Lee";
      case "starbuck":
      case 'kara "starbuck" thrace':
      case "kara":
        return "Starbuck";
      case "boomer":
      case 'sharon "boomer" valerii':
      case "valerii":
      case "sharon":
        return "Boomer";
      case "athena":
      case 'sharon "athena" agathon':
      case "number eight":
      case "eight":
        return "Athena";
      case "chief":
      case "galen":
      case "tyrol":
      case '"chief" galen tyrol':
      case 'galen "chief" tyrol':
      case "galen tyrol":
        return "Chief";
      case "helena cain":
      case "helena":
      case "cain":
        return "Cain";
      case "ellen":
      case "ellen tigh":
        return "Ellen";
      case "kat":
      case "sasha":
      case 'louanne "kat" katraine':
        return "Kat";
      case "dee":
      case "dualla":
      case "anastasia":
      case 'anastasia "dee" dualla':
      case "d":
        return "Dee";
      case "felix":
      case "gaeta":
      case "felix gaeta":
        return "Gaeta";
      case "tory":
      case "tory foster":
      case "foster":
        return "Tory";
      case "longshot":
      case "anders":
      case "samuel t. anders":
      case "sam":
      case "samuel t anders":
        return "Anders";
      case "cally":
      case 'callandra "cally" tyrol':
      case "callandra":
        return "Cally";
      case "hoshi":
      case "louis hoshi":
        return "Hoshi";
      case "romo lampkin":
      case "romo":
      case "lampkin":
        return "Romo";
      case "hotdog":
      case "hot dog":
      case 'brendan "hot dog" costanza':
      case 'brenden "hot dog" costanza':
      case "bodie olmos":
        return "Hot Dog";
      case "doc":
      case "sherman":
      case "cottle":
      case "doc cottle":
      case 'sherman "doc" cottle':
      case '"doc" sherman cottle':
        return "Cottle";
      case "one":
      case "number one":
      case "cavil":
      case "brother cavil":
        return "Cavil";
      case "two":
      case "number two":
      case "leoben":
      case "leoben conoy":
        return "Leoben";
      case "number three":
      case "three":
      case "d'anna":
      case "d'anna biers":
      case "deanna":
        return "D'Anna";
      case "four":
      case "number four":
      case "simon":
      case "simon o'neill":
        return "Simon";
      case "five":
      case "number five":
      case "doral":
      case "aaron doral":
        return "Doral";
      case "six":
      case "number six":
      case "caprica six":
      case '"caprica" six':
      case "caprica":
        return "Six";
      default:
        return "NONE";
    }
  }
  function parseCharacter(char) {
    var parsed = parseCharacter2(char);
    var cylonLeaderYet = false;
    for (var i = 0; !(i >= z.players.length) && !cylonLeaderYet; i++) {
      cylonLeaderYet = isCylonLeader(z.players[i]);
    }

    if (parsed === "NONE") {
      return "NONE";
    }
    if (isCylonLeader(parsed) && cylonLeaderYet) {
      return "NONE";
    }
    var valid = false;
    switch (parsed) {
      case "Adama":
      case "Tigh":
      case "Helo":
      case "Roslin":
      case "Baltar":
      case "Zarek":
      case "Apollo":
      case "Starbuck":
      case "Boomer":
      case "Chief":
        valid = true;
        break;
      case "Cain":
      case "Ellen":
      case "Kat":
      case "Dee":
      case "Six":
      case "Leoben":
      case "Cavil":
        valid = z.pegasus;
        break;
      case "Gaeta":
      case "Tory":
      case "Anders":
      case "Cally":
        valid = z.exodus;
        break;
      case "Hoshi":
      case "Romo":
      case "Hot Dog":
      case "Cottle":
      case "Tom":
      case "Lee":
      case "Karl":
      case "Gaius":
      case "Doral":
      case "Simon":
      case "D'Anna":
      case "Athena":
        valid = z.daybreak;
        break;
    }
    if (!valid) {
      return "NONE";
    }

    return parsed;
  }
  function onGalactica(location) {
    return (
      location === "Brig" ||
      location === "Sickbay" ||
      location === "FTL Control" ||
      location === "Weapons Control" ||
      location === "Communications" ||
      location === "Research Lab" ||
      location === "Command" ||
      location === "Admiral's Quarters" ||
      location === "Hangar Deck" ||
      location === "Armory"
    );
  }
  function activateLocation(player, location) {
    t.value += bold(z.players[player] + " activates " + location + ".\r\n");
    if (
      location === "FTL Control" ||
      location === "Weapons Control" ||
      location === "Armory" ||
      location === "Pegasus CIC" ||
      location === "Main Batteries"
    ) {
      SPToken(location);
    } else if (
      location === "Admiral's Quarters" ||
      location === "Airlock" ||
      location === "Detention" ||
      location === "Resistance HQ"
    ) {
      var target = prompt("Who are you targeting?");
      if (target === null) {
        return null;
      }
      target = parseCharacter(target);
      if (!characterPresent(target)) {
        alert("That character is not in the game.");
        return null;
      }
      t.value += bold(z.players[player] + " targets " + target + ".\r\n");
      startLocationSkillCheck(location, getPlayerNum(target));
    } else if (location === "Brig") {
      startLocationSkillCheck("Brig",myPlayerNum);
    } else if (location === "Administration" && !z.daybreak) {
      for (var i = 0; !(i >= z.numPlayers); i++) {
        for (var j = 0; !(j >= z.quorumTitles[i].length); j++) {
          if (z.quorumTitles[i][j] === 5 && i !== z.president) {
            t.value +=
              titleList(i) +
              " " +
              z.players[i] +
              " will become President if this skill check passes.\r\n";
            startLocationSkillCheck("Administration", i);
          }
        }
      }
      var target = prompt(
        "Who will become President if this skill check passes?"
      );
      if (target === null) {
        return null;
      }
      target = parseCharacter(target);
      alert("Targeting " + target + ".");
      if (!characterPresent(target)) {
        alert("That character is not in the game.");
        return null;
      }
      target = getPlayerNum(target);
      if (target === z.president) {
        if (
          !confirm(
            z.players[target] +
              " is already the President. Are you sure you want to continue? (The pass and fail effects of this skill check will be No Effect.)"
          )
        ) {
          return null;
        }
      }
      t.value += bold(
        z.players[player] +
          " chooses " +
          z.players[target] +
          " to become President if this skill check passes.\r\n"
      );
      startLocationSkillCheck("Administration", target);
    } else if (
      (location === "Press Room" && !z.daybreak) ||
      (location === "President's Office" && z.daybreak)
    ) {
      dealSkillCard(player, 0);
      dealSkillCard(player, 0);
      alert(
        "You drew " +
          z.skillCardHands[player][z.skillCardHands[player].length - 2] +
          " and " +
          z.skillCardHands[player][z.skillCardHands[player].length - 1] +
          "."
      );
    } else if (
      (location === "President's Office" && !z.daybreak) ||
      (location === "Quorum Chamber" && z.daybreak)
    ) {
      dealQuorumCard();
      alert("You drew " + z.quorumHand[z.quorumHand.length - 1] + ".");
      t.value +=
        "President " +
        z.players[player] +
        " draws a Quorum Card.  They may now play one or draw another.\r\n";
    }
  }
  /* used for Zarek, Leoben */
  function otherPlayerInLocation(player, location) {
    for (var i = 0; !(i >= z.numPlayers); i++) {
      if (i !== player) {
        if (z.playerLocations[i] === location) {
          return true;
        }
      }
    }
    return false;
  }
  var re = new RegExp(
    "\\[size=1\\]\\[color=#F4F4FF\\]New seed: \\S+\\[/color\\]\\[/size\\]",
    "g"
  );
  function postSeed() {
    var bannerRegExp = new RegExp(
      "\\[ima" + "geid=" + z.banners[myPlayerNum] + " medium\\]",
      "g"
    );
    t.value =
      "[ima" +
      "geid=" +
      z.banners[myPlayerNum] +
      " medium]\r\n" +
      t.value.replace(bannerRegExp, "");

    var splitted = window.btoa(JSON.stringify(z)).match(/.{1,20}/g);
    var text = "";
    while (splitted.length > 0) {
      text += splitted.shift() + "-";
    }
    t.value = t.value.replace(re, "") + size(invisible("New seed: " + text), 1);
  }
  var seed = re.exec(t.value);
  if (seed === null) {
    seed = "";
  } else {
    seed = seed[0].slice(33, -15);
  }
  if (seed === "") {
    seed = prompt("Enter seed.");
    if (seed === null) {
      return 0;
    }
  }
  seed = window.atob(seed.replace(/-/g, ""));
  z = JSON.parse(seed);

  myPlayer = z.players[myPlayerNum];
  myCharacter = z.playerCharacters[myPlayerNum];

  var proceed = true;
  while (proceed) {
    var options = [];
    options.push("Print Hand Report (and exit)");
    options.push("Draw Skill Cards");
    /* Move Helo Automatically */
    if (z.playerLocations[myPlayerNum] !== "Stranded on Caprica") {
      options.push("Move");
    }
    for (var i = 0; !(i >= 3) && z.preCrossroads; i++) {
      if (z.playerLocations[myPlayerNum] === z.allyLocations[z.allies[i]]) {
        options.push("Meet an Ally on your location.");
        break;
      }
    }
    var myLocation = z.playerLocations[myPlayerNum];

    /* */
    if (
      myLocation !== "Sickbay" &&
      myLocation !== "Medical Center" &&
      myLocation !== "Sector 1" &&
      myLocation !== "Sector 2" &&
      myLocation !== "Sector 3" &&
      myLocation !== "Sector 4" &&
      myLocation !== "Sector 5" &&
      myLocation !== "Sector 6" &&
      (myPlayer !== "Roslin" || z.skillCardHands[myPlayerNum].length >= 2) &&
      (myLocation !== "Engine Room" ||
        z.skillCardHands[myPlayerNum].length >= 4 ||
        (myPlayer !== "Roslin" && z.skillCardHands[myPlayerNum].length >= 2)) &&
      (myPlayer !== "Cain" ||
        (myLocation !== "Engine Room" && myLocation !== "FTL Control")) &&
      (myPlayer !== "Adama" || myLocation !== "Admirals' Quarters") &&
      (myPlayer !== "Six" ||
        myLocation !== "Cylon Fleet" ||
        z.skillCardHands[myPlayerNum].length >= 1) &&
      (myPlayer !== "Zarek" ||
        !otherPlayerInLocation(myPlayerNum, myLocation)) &&
      (myPlayer !== "Adama" || myLocation !== "Admiral's Quarters") &&
      (myLocation !== "FTL Control" || z.jumpTrack >= 3) &&
      (myLocation !== "Quorum Chamber" || z.president === myPlayerNum) &&
      (myLocation !== "President's Office" ||
        z.daybreak ||
        z.president === myPlayerNum)
    ) {
      options.push("Activate " + z.playerLocations[myPlayerNum]);
    }
    if (
      z.skillCardHands[myPlayerNum].length > 0 &&
      (z.revealedCylons[myPlayerNum] !== 1 || (z.pegasus && !z.daybreak))
    ) {
      options.push("Play a Skill Card");
    }
    if (z.skillCardHands[myPlayerNum].length > 0) {
      options.push("Discard a Skill Card");
    }
    if (
      z.skillCardHands[myPlayerNum].length > 0 &&
      z.revealedCylons[myPlayerNum] !== 1
    ) {
      options.push("Discard a random Skill Card");
    }
    if (
      z.skillCardHands[myPlayerNum].length > 0 &&
      z.currentSkillCheck !== null
    ) {
      options.push("Play a card into the skill check");
    }
    if (
      z.playerLocations[myPlayerNum] !== "Brig" &&
      z.revealedCylons[myPlayerNum] !== 1 &&
      z.currentCrisis === null &&
      z.currentSkillCheck === null
    ) {
      if (myPlayer !== "Roslin") {
        options.push("Play the top Crisis");
      } else if (myPlayer === "Roslin") {
        options.push("Religious Visions");
      }
    }
    if (
      z.currentCrisis !== null &&
      z.currentSkillCheck === null &&
      d.currentPlayerChooses[z.currentCrisis] === 1
    ) {
      options.push("Choose the Skill Check on this crisis");
    }
    options.push("Modify Game State");
    options.push("Other Options");

    var promptText =
      "What would you like to do? (1-" + options.length + ")\n\n";
    for (var i = 0; !(i >= options.length); i++) {
      promptText += i + 1 + ": " + options[i] + ".\n";
    }

    var prompted = parseInt(prompt(promptText));

    if (isNaN(prompted) || !(prompted > 0) || prompted > options.length) {
      /* TODO: seed output, token output */
      postSeed();
      proceed = false;
    } else if (options[prompted - 1] === "Draw Skill Cards") {
      var drawingSkillCards = true;
      while (drawingSkillCards) {
        options = [];
        /* TODO: Sympathetic Cylon handling. */
        var myLocation = z.playerLocations[myPlayerNum];
        if (
          myLocation !== "Hub Destroyed" &&
          myLocation !== "Sickbay" &&
          myLocation !== "Medical Center" &&
          myPlayer !== "D'Anna" &&
          (myPlayer !== "Athena" ||
            (myLocation !== "Brig" &&
              myLocation !== "Resurrection Ship" &&
              myLocation !== "Detention")) &&
          (z.round !== 1 || myPlayer !== "Anders") &&
          (myPlayer !== "Karl" || onGalactica(myLocation)) &&
          (z.revealedCylons[myPlayerNum] === 0 || isCylonLeader(myPlayer))
        ) {
          options.push("Receive Skills (start of turn draw).");
        }
        if (d.skillSets[0][myCharacter] === 0) {
          options.push("Draw 1 Politics [not in skill set].");
        } else {
          options.push("Draw 1 Politics.");
        }
        if (d.skillSets[1][myCharacter] === 0) {
          options.push("Draw 1 Leadership [not in skill set].");
        } else {
          options.push("Draw 1 Leadership.");
        }
        if (d.skillSets[2][myCharacter] === 0) {
          options.push("Draw 1 Tactics [not in skill set].");
        } else {
          options.push("Draw 1 Tactics.");
        }
        if (d.skillSets[3][myCharacter] === 0) {
          options.push("Draw 1 Piloting [not in skill set].");
        } else {
          options.push("Draw 1 Piloting.");
        }
        if (d.skillSets[4][myCharacter] === 0) {
          options.push("Draw 1 Engineering [not in skill set].");
        } else {
          options.push("Draw 1 Engineering.");
        }
        if (z.pegasus || z.daybreak) {
          if (d.skillSets[5][myCharacter] === 0) {
            options.push("Draw 1 Treachery [not in skill set].");
          } else {
            options.push("Draw 1 Treachery.");
          }
        }

        promptText =
          "What skill card(s) would you like? (1-" + options.length + ")\r\n";
        for (var i = 0; !(i >= options.length); i++) {
          promptText += i + 1 + ": " + options[i] + "\n";
        }

        prompted = parseInt(prompt(promptText));
        if (!isNaN(prompted) && prompted >= 1 && !(prompted > options.length)) {
          if (
            options[prompted - 1] === "Receive Skills (start of turn draw)."
          ) {
            var cardsDealt = "You received:\r\n";
            var cardCount = 0;
            for (i = 0; !(i >= 6); i++) {
              for (var j = d.skillDraws[i][myCharacter]; j > 0; j--) {
                dealSkillCard(myPlayerNum, i);
                cardsDealt +=
                  cardText(
                    z.skillCardHands[myPlayerNum][
                      z.skillCardHands[myPlayerNum].length - 1
                    ]
                  ) + "\n";
                cardCount++;
              }
            }
            alert(cardsDealt);
            if ((myPlayer === "Baltar" && cardCount === 4) || cardCount === 5) {
              drawingSkillCards = false;
            } else {
              alert(
                "You have a variable draw; draw the remainder of your draw manually."
              );
            }
          } else {
            var startDraw = 1;
            if (
              options[0] === "Draw 1 Politics." ||
              options[0] === "Draw 1 Politics [not in skill set]."
            ) {
              startDraw = 0;
            }
            for (var i = startDraw; !(i >= startDraw + 6); i++) {
              if (prompted === i) {
                dealSkillCard(myPlayerNum, i - startDraw);
                alert(
                  "You drew: " +
                    cardText(
                      z.skillCardHands[myPlayerNum][
                        z.skillCardHands[myPlayerNum].length - 1
                      ]
                    )
                );
              }
            }
          }
        } else {
          drawingSkillCards = false;
        }
      }
    } else if (options[prompted - 1].slice(0, 8) === "Activate") {
      activateLocation(myPlayerNum, options[prompted - 1].slice(9));
    } else if (options[prompted - 1] === "Move") {
      var prompting = true;
      while (prompting) {
        var prompted = prompt("Where would you like to move?");
        if (prompted !== null) {
          prompted = parseLocation(prompted);
          if (prompted === "NONE") {
            alert("Invalid Location.");
          } else {
            alert("You moved to " + prompted + ".");
            movePlayer(myPlayerNum, prompted);
            prompting = false;
            for (var j = 0; !(j >= 3) && z.preCrossroads; j++) {
              if (prompted === z.allyLocations[z.allies[j]]) {
                alert(
                  "You just moved to a location containing an Ally.  You may need to meet them now."
                );
                break;
              }
            }
          }
        } else {
          prompting = false;
        }
      }
    } else if (options[prompted - 1] === "Discard a Skill Card") {
      var promptText =
        "What card would you like to discard? (1-" +
        z.skillCardHands[myPlayerNum].length +
        ")";
      /* TODO: Better Love handling. */
      if (characterPresent("Athena") && myPlayer !== "Athena") {
        promptText +=
          "\nIf Athena has not already loved this turn, wait for her to play or pass on For Love before discarding.";
      }
      for (var i = 0; !(i >= z.skillCardHands[myPlayerNum].length); i++) {
        promptText += "\n"+(i+1)+": " + cardText(z.skillCardHands[myPlayerNum][i]);
      }
      var prompting = true;
      while (prompting) {
        var prompted = prompt(promptText);
        if (prompted === null) {
          break;
        }
        prompted = parseInt(prompted);
        if (
          !isNaN(prompted) &&
          prompted >= 1 &&
          !(prompted > z.skillCardHands[myPlayerNum].length)
        ) {
          /* We do not auto-draw mutiny if you discard dradis/bait, as you could discard your whole hand?  Perhaps prompt, though.*/
          alert(
            "Discarding " + cardText(z.skillCardHands[myPlayerNum][prompted - 1]) + "."
          );
          discardSkillCard(myPlayerNum, prompted - 1);
          prompting = false;
        }
      }
    } else if (options[prompted - 1] === "Discard a random Skill Card.") {
      var confirmText =
        "Are you sure you would like to discard a random skill card?";
      if (characterPresent("Athena") && myPlayer !== "Athena") {
        confirmText +=
          "\nIf Athena has not already loved this turn, wait for her to play or pass on For Love before discarding.";
      }
      if (confirm(confirmText)) {
        var discard = discardRandomSkillCard(myPlayerNum);
        alert("Discarded " + cardText(discard) + " randomly.");
      }
    } else if (options[prompted - 1] === "Play the top Crisis") {
      playCrisis();
      var alertText = "Played Crisis: " + d.crisisNames[z.currentCrisis] + ".";
      if (
        d.currentPlayerChooses[z.currentCrisis] === 1 ||
        (myPlayerNum === z.admiral &&
          d.admiralChooses[z.currentCrisis] === 1) ||
        (myPlayerNum === z.president &&
          d.presidentChooses[z.currentCrisis] === 1) ||
        (myPlayerNum === z.cag && d.cagChooses[z.currentCrisis] === 1)
      ) {
        alertText += "\nIt's your choice on this crisis.";
      }
      alert(alertText);
    } else if (
      options[prompted - 1] === "Choose the Skill Check on this crisis"
    ) {
      t.value += bold(
        myPlayer +
          " chooses the top option for " +
          d.crisisNames[z.currentCrisis] +
          ".\r\n"
      );
      alert(
        "Initializing skill check: " + d.crisisNames[z.currentCrisis] + "."
      );
      startCrisisSkillCheck();
    } else if (options[prompted - 1] === "Print Hand Report (and exit)") {
      var report =
        bold(titleList(myPlayerNum)) +
        bold(myPlayer) +
        ", your current hand is:\r\n";
      for (var j = 0; !(j >= z.skillCardHands[myPlayerNum].length); j++) {
        report += cardText(z.skillCardHands[myPlayerNum][j]) + "\r\n";
      }
      var excessCards = z.skillCardHands[myPlayerNum] - 10;
      if (myPlayer === "Chief") {
        excessCards += 2;
      }
      if (excessCards > 0) {
        report += "You are over your hand limit by ";
        if (excessCards === 1) {
          report += bold("1 card");
        } else {
          report += bold(excessCards + " cards");
        }
        report += " and may need to discard at the end of the turn.\r\n";
      }
      report += "\r\n";
      if (z.daybreak && z.mutinies[myPlayerNum].length > 0) {
        report += bold("Your Mutinies are") + ":\r\n";
        for (var j = 0; !(j >= z.mutinies[myPlayerNum].length); j++) {
          report += d.mutinyNames[z.mutinies[myPlayerNum][j]] + "\r\n";
        }
        if (
          z.mutinies[myPlayerNum].length === 3 ||
          (z.mutinies[myPlayerNum].length === 2 &&
            z.theMutineer !== myPlayerNum)
        ) {
          report += bold("You must discard a Mutiny now.") + "\r\n";
        }
        report += "\r\n";
      }

      if (myPlayer === "Tom" && z.necessarySteps.length > 0) {
        report += bold(
          "Necessary Steps for " + z.players[z.necessarySteps[0]] + ":\r\n"
        );
        report += d.mutinyNames[z.necessarySteps[1]];
        report += d.mutinyNames[z.necessarySteps[2]];
        report += bold(
          "Pick one to give to " +
            z.players[z.necessarySteps[0]] +
            "; bottom the other.\r\n\r\n"
        );
      }

      if (myPlayerNum === z.president) {
        if (isMale(myPlayerNum)) {
          report += bold("Mr. ");
        } else {
          report += bold("Madam ");
        }
        report += bold("President, your Quorum hand is:\r\n");
        for (var j = 0; !(j >= z.quorumHand.length); j++) {
          report += d.quorumNames[z.quorumHand[j]] + "\r\n";
        }
        if (z.quorumHand.length > z.quorumHandLimit) {
          report +=
            bold(
              "You are over your Quorum hand limit by " +
                (z.quorumHand.length - z.quorumHandLimit) +
                " cards"
            ) + ", and may need to discard at the end of the turn.\r\n";
        }
        report += "\r\n";
      }

      if (myPlayerNum === z.admiral) {
        report +=
          bold(colorText("green","Admiral")) + ", you have " + z.nukes + " nuke tokens.\r\n\r\n";
      }

      /*TODO: Sympathetic Cylon handling */
      if (myPlayerNum !== z.theCylonLeader) {
        report += bold("Your Loyalty hand is:\r\n");
      } else if (z.daybreak) {
        report += bold("Your Motive hand is:\r\n");
      } else {
        report += bold("Your Agenda is:\r\n");
      }
      for (var j = 0; !(j >= z.loyaltyHands[myPlayerNum].length); j++) {
        report += d.loyaltyNames[z.loyaltyHands[myPlayerNum][j]] + "\r\n";
      }
      for (var j = 0; !(j >= z.loyaltyDiscards[myPlayerNum].length); j++) {
        report +=
          strikethrough(d.loyaltyNames[z.loyaltyDiscards[myPlayerNum][j]]) +
          "\r\n";
      }
      report += "\r\n";

      if (z.preCrossroads) {
        report +=
          "You have " +
          colorText("blue", z.benevolent[myPlayerNum]) +
          " Benevolent Trauma.\r\n";
        report +=
          "You have " +
          colorText("red", z.antagonistic[myPlayerNum]) +
          " Antagonistic Trauma.\r\n";
      }
      t.value += spoiler(report);
      postSeed();
      proceed = false;
    }
  }
 
})();


Comments