${locations.map(location=>html`
${location.Name} ${location.Description} `)} End Turn Undo `}connectedCallback(){this.Render();this.addEventListener("drop",e=>{let side=e.target;let data=e.dataTransfer.getData("text/plain");let card=document.getElementById(data);if(card){if(card.Controller.DynamicCost){card.Controller.AddModifier(card.Controller,"setcost",card.Controller.DynamicCost)}card.Controller.Owner.CurrentEnergy-=card.Controller.CurrentCost;card.Controller.Owner.Element.Render();this.PlayedCardsQueue.push(card.Controller);this.Log(new Trace,`You play ${card.Controller} to ${side.Location}`)}});this.shadowRoot.addEventListener("click",e=>{let target=e.target;if(target.id==="end"){switch(this.State){case"play":this.RunEndTurn();break;case"won":this.Game.ProgressToNextOpponent();break;case"lost":this.Game.ShowSummary(false);break}}else if(target.id==="undo"){let card=this.PlayedCardsQueue.pop();if(card&&card.Owner===this.Player&&!card.IsRevealed){card.Owner.CurrentEnergy+=card.CurrentCost;card.Owner.Element.Render();if(card.DynamicCost){card.RemoveModifiers(card)}this.Player.Hand.append(card.Element);let log_element=this.querySelector("a-log");log_element?.lastElementChild?.remove()}}else if(target.id==="skip"){this.InitBattle()}else if(target.id==="reroll"){this.Reroll()}})}RenderChildren(){this.Player.Element.Render();this.Villain.Element.Render();for(let location of this.Locations){location.Element.Render()}}GetRarity(){const random=float();if(random<.8){return"Common"}else if(random<.98){return"Uncommon"}else{return"Rare"}}Reroll(){let all_cards_by_rarity_and_cost=this.Game.Collection.AllCardsByRarityAndCost();let card_elements=this.querySelectorAll("a-card[slot='shop']");let used_card_types=new Set;card_elements.forEach((card,index)=>{let cost=index%6+1;let rarity=this.GetRarity();let cards_of_same_cost=all_cards_by_rarity_and_cost[rarity][cost];let cards_with_dynamic_cost=all_cards_by_rarity_and_cost[rarity][0]||[];if(cards_of_same_cost&&cards_of_same_cost.length>1){let new_card_type;do{let new_card=element([...cards_of_same_cost,...cards_with_dynamic_cost]);new_card_type=(new_card?.Sprite||65).toString()}while(new_card_type===card.getAttribute("type")||used_card_types.has(new_card_type));card.setAttribute("type",new_card_type);used_card_types.add(new_card_type);card.classList.add("frontside");card.classList.remove("dragging");card.draggable=true;card.addEventListener("dragstart",e=>{let card2=e.target;if(e.dataTransfer){e.dataTransfer.setData("text/plain",card2.id)}})}});this.Game.Gold-=3;this.Render()}PrepareBattle(){set_seed(this.Game.Seed*this.Game.CurrentOpponent);this.Render();let all_cards=this.Game.Collection.AllCardsByRarityAndCost();for(let row=0;row `}this.insertAdjacentHTML("beforeend",result)}for(let card of this.querySelectorAll("a-card")){card.addEventListener("dragstart",e=>{let card2=e.target;if(e.dataTransfer){e.dataTransfer.setData("text/plain",card2.id)}});save_card_state(card.Controller,1)}let player_cards=[];for(let card_type of this.Game.PlayerDeck){let card=document.createElement("a-card");card.setAttribute("type",card_type.toString());card.setAttribute("slot","deck");card.classList.add("frontside");card.addEventListener("dragover",e=>{e.preventDefault()});card.addEventListener("drop",e=>{e.preventDefault();e.stopPropagation();if(e.dataTransfer){const data=e.dataTransfer.getData("text/plain");const new_card=document.getElementById(data);if(new_card){let price=parseInt(new_card.getAttribute("gold")||"1",10);if(price>this.Game.Gold){return false}new_card.setAttribute("draggable","false");let backcard=new_card.cloneNode(true);backcard.classList.remove("frontside");new_card.replaceWith(backcard);let offset=this.Game.PlayerDeck.indexOf(card.Controller.Sprite);this.Game.PlayerDeck.splice(offset,1,new_card.Controller.Sprite);new_card.setAttribute("slot","deck");card.replaceWith(new_card);save_card_state(new_card.Controller,2);this.Game.Stats["Cards Acquired"]++;this.Game.Gold-=price;this.Render()}}});player_cards.push(card);save_card_state(card.Controller,1|2)}player_cards.sort(CardElement.Compare);this.append(...player_cards)}async InitBattle(){this.State="play";this.Render();this.Game.Stats["Battles"]++;for(let[trace,message]of this.StartBattle()){this.Log(trace,message);this.RenderChildren();await delay(150)}}*StartBattle(){let trace=new Trace;yield*this.Villain.StartBattle(trace);yield*this.Player.StartBattle(trace);yield*this.BroadcastGameMessage(1);yield*this.StartTurn()}*StartTurn(){let trace=new Trace;this.CurrentTurn++;this.TheButton.textContent=`End Turn ${this.CurrentTurn}`;yield trace.Log(`Turn ${this.CurrentTurn} of ${this.MaxTurns} `);yield*this.Player.StartTurn(this.CurrentTurn,trace);yield*this.Villain.StartTurn(this.CurrentTurn,trace);if(this.CurrentTurn<4){let location=this.Locations[this.CurrentTurn-1];yield*location.Reveal(trace)}yield*this.BroadcastGameMessage(3);yield*this.Villain.VillAIn(trace);yield trace.Log(" ");this.TheButton.disabled=false}async RunEndTurn(){this.CardMovedLastTurn=false;for(let[trace,message]of this.EndTurn()){this.Log(trace,message);this.RenderChildren();await delay(150)}}*EndTurn(){let trace=new Trace;yield trace.Log(" ");this.TheButton.disabled=true;for(let card of this.querySelectorAll("a-table a-card")){if(!card.Controller.IsRevealed){card.classList.remove("frontside")}}let unrevealed_cards=this.PlayedCardsQueue.filter(card=>!card.IsRevealed);for(let card of unrevealed_cards){yield*this.BroadcastCardMessage(11,trace,card);yield*card.Reveal(trace);if(card.Owner===this.Player){this.Game.Stats["Cards Played"]++;this.Game.Stats["Energy Spent"]+=card.CurrentCost}}yield*this.BroadcastGameMessage(4);if(this.CurrentTurn>=this.MaxTurns){yield*this.EndBattle()}else{yield*this.StartTurn()}}*EndBattle(){let trace=new Trace;let locations_won=[];for(let location of this.Locations){let score=location.GetScore(this.Player);if(score>=location.GetScore(this.Villain)){locations_won.push(location)}this.Game.Stats["Total Power"]+=score}this.Game.CardsInShop=locations_won.length;this.Game.Gold+=locations_won.length;this.Game.Stats["Locations Won"]+=locations_won.length;this.Game.Stats["Locations Lost"]+=this.Locations.length-locations_won.length;this.TheButton.disabled=true;let player_score=this.Player.GetScore();let villain_score=this.Villain.GetScore();if(player_score>villain_score||player_score===villain_score&&locations_won.length>1){this.State="won";yield trace.Log(`You win ${player_score} \u2014 ${villain_score}! `);yield trace.Log(`You win ${locations_won.join(", ")}.`);yield trace.Log(`Choose ${locations_won.length} card(s) in the shop. `);yield trace.Log(`Next! `)}else{this.State="lost";yield trace.Log(`You lose ${player_score} \u2014 ${villain_score}! `);yield trace.Log(`Summary `)}yield*this.BroadcastGameMessage(2)}*BroadcastGameMessage(kind){let processed=[];let trace=new Trace;for(let location of this.Locations){if(location.IsRevealed&&!trace.includes(location)&&!processed.includes(location)){yield*location.OnMessage(kind,trace.Fork(location));processed.push(location)}for(let card of location.GetRevealedCards()){if(!trace.includes(card)&&!processed.includes(card)){yield*card.OnMessage(kind,trace.Fork(card));processed.push(card)}}}}*BroadcastCardMessage(kind,trace,card){let processed=[];yield*card.OnMessageSelf(kind,trace.Fork(card));let card_location=card.Field;if(card_location){if(card_location.IsRevealed&&!trace.includes(card_location)&&!processed.includes(card_location)){yield*card_location.OnMessage(kind,trace.Fork(card_location),card);processed.push(card_location)}for(let other of card_location.GetRevealedCards()){if(other.Element!==card.Element&&!trace.includes(other)&&!processed.includes(other)){yield*other.OnMessage(kind,trace.Fork(other),card);processed.push(other)}}}let other_locations=this.Locations.filter(location=>location!==card_location);for(let other_location of other_locations){for(let other_card of other_location.GetRevealedCards()){if(other_card.Element!==card.Element&&!trace.includes(other_card)&&!processed.includes(other_card)){yield*other_card.OnMessage(kind,trace.Fork(other_card),card);processed.push(other_card)}}}}*GetRevealedCards(actor){let revealed_cards=[...this.querySelectorAll("a-card")].map(card=>card.Controller).filter(card=>card.IsRevealed);for(let card of revealed_cards){if(!actor||card.Owner===actor){yield card}}}GetPossibleLocations(card){return this.Locations.filter(location=>!location.IsFull(card.Owner)&&(!location.IsRevealed||location.CanBePlayedHere(card))&&card.CanBePlayedHere(location))}GetNonFullLocations(actor){return this.Locations.filter(location=>!location.IsFull(actor))}CleanUp(card){let modifiers=this.querySelectorAll(`a-modifier[origin="${card.Id}"]`);for(let modifier of modifiers){modifier.remove()}}Log(trace,message){const logDisplay=this.querySelector("a-log");if(logDisplay){let tabs=trace.map(item=>typeof item==="number"?item:1).reduce((a,b)=>a+b,0);let indent=new Array(tabs).fill("\u2026").join(" ");logDisplay.insertAdjacentHTML("beforeend",`${indent} ${message}
`);logDisplay.scrollTo({top:logDisplay.scrollHeight,behavior:"smooth"})}}};customElements.define("battle-scene",BattleScene);var CollectionTitle=class extends HTMLElement{constructor(){super();this.attachShadow({mode:"open"})}connectedCallback(){this.render()}render(){let collection=get_collection_state();let all_cards=[];let known_cards_count=0;let owned_cards_count=0;for(let card_type in CardElement.Controllers){let card=document.createElement("a-card");card.setAttribute("type",card_type);card.classList.add("frontside");if(card.Controller.IsVillain){continue}if(collection.cards[card.Controller.Name]&1){known_cards_count++}else{card.classList.add("unknown")}if(collection.cards[card.Controller.Name]&2){owned_cards_count++}else{card.classList.add("unowned")}all_cards.push(card)}all_cards.sort(CardElement.Compare);this.shadowRoot.innerHTML=html` ${all_cards.map(card=>card.outerHTML).join("")} Millennials ${known_cards_count}
${format_percent(known_cards_count/all_cards.length)} seen ${owned_cards_count}
${format_percent(owned_cards_count/all_cards.length)} unlocked `}get AllCards(){let card_elements=this.shadowRoot.querySelectorAll("a-card");return Array.from(card_elements,card=>card.Controller)}AllCardsByCost(){return Object.groupBy(this.AllCards,card=>clamp(1,6,card.Cost))}};customElements.define("collection-title",CollectionTitle);var CollectionViewer=class extends HTMLElement{groupByCost=true;showWipCards=true;showVillains=false;filterRarity="all";constructor(){super();this.attachShadow({mode:"open"})}connectedCallback(){this.render();this.shadowRoot.addEventListener("click",e=>{let target=e.target;switch(target.id){case"toggle-group-by-cost":this.toggleGroupByCost();break;case"toggle-show-wip-cards":this.toggleShowWipCards();break;case"toggle-show-villain-cards":this.toggleShowVillainCards();break;case"filter-rarity-all":this.filterByRarity("all");break;case"filter-rarity-common":this.filterByRarity("common");break;case"filter-rarity-uncommon":this.filterByRarity("uncommon");break;case"filter-rarity-rare":this.filterByRarity("rare");break;case"filter-rarity-legendary":this.filterByRarity("legendary");break}})}toggleGroupByCost(){this.groupByCost=!this.groupByCost;this.render()}toggleShowWipCards(){this.showWipCards=!this.showWipCards;this.render()}toggleShowVillainCards(){this.showVillains=!this.showVillains;this.render()}filterByRarity(rarity){this.filterRarity=rarity;this.render()}render(){let collection=get_collection_state();let all_cards=[];let cards_by_cost={};let known_cards_count=0;let owned_cards_count=0;for(let card_type in CardElement.Controllers){let card=document.createElement("a-card");card.setAttribute("type",card_type);card.classList.add("frontside");if(this.showVillains&&!card.Controller.IsVillain){continue}else if(!this.showVillains&&card.Controller.IsVillain){continue}if(!this.showWipCards&&card.Controller.Description===""){continue}if(this.filterRarity!=="all"&&card.Controller.Rarity.toLowerCase()!==this.filterRarity){continue}if(collection.cards[card.Controller.Name]&1){known_cards_count++}else{}if(collection.cards[card.Controller.Name]&2){owned_cards_count++}else{}all_cards.push(card);let cost=card.Controller.CurrentCost;if(cost<1){cost=1}else if(cost>6){cost=6}if(!cards_by_cost[cost]){cards_by_cost[cost]=[]}cards_by_cost[cost].push(card)}all_cards.sort(CardElement.Compare);let content;if(this.groupByCost){let cost_sections=Object.keys(cards_by_cost).sort((a,b)=>parseInt(a)-parseInt(b)).map(cost=>{let cards=cards_by_cost[cost];return html` ${cost}-Cost (${cards.length}) ${cards.map(card=>card.outerHTML).join("")} `}).join("");content=html` Card Collection (total: ${all_cards.length}, seen: ${known_cards_count}, unlocked: ${owned_cards_count}) ${this.groupByCost?"Ungroup by Cost":"Group by Cost"} ${this.showWipCards?"Hide WIP Cards":"Show WIP Cards"} ${this.showVillains?"Hide Villains":"Show Villains"} Rarity: All Common Uncommon Rare Legendary ${cost_sections} `}else{content=html` Card Collection (total: ${all_cards.length}, seen: ${known_cards_count}, unlocked: ${owned_cards_count}) ${this.groupByCost?"Ungroup by Cost":"Group by Cost"} ${this.showWipCards?"Hide WIP Cards":"Show WIP Cards"} ${this.showVillains?"Hide Villains":"Show Villains"} Rarity: All Common Uncommon Rare Legendary ${all_cards.map(card=>card.outerHTML).join("")} `}this.shadowRoot.innerHTML=html` ${content} `}get AllCards(){let card_elements=this.shadowRoot.querySelectorAll("a-card");return Array.from(card_elements,card=>card.Controller)}AllCardsByCost(){return Object.groupBy(this.AllCards,card=>clamp(1,6,card.Cost))}AllCardsByRarityAndCost(){const groupedByRarity=Object.groupBy(this.AllCards,card=>card.Rarity);const result={Common:{},Uncommon:{},Rare:{},Legendary:{}};for(const[rarity,cards]of Object.entries(groupedByRarity)){result[rarity]=Object.groupBy(cards,card=>clamp(0,6,card.Cost))}return result}};customElements.define("collection-viewer",CollectionViewer);var LocationOwner=class extends HTMLElement{constructor(){super();this.attachShadow({mode:"open"})}get Location(){let location=this.closest("a-location");return location.Controller}connectedCallback(){this.shadowRoot.innerHTML=html` `;if(this.slot==="player"){this.addEventListener("dragover",e=>{e.preventDefault()});this.addEventListener("drop",e=>{e.preventDefault();if(this.childElementCount>=4){alert("Location is full");e.stopPropagation();return}const data=e.dataTransfer.getData("text/plain");const card=document.getElementById(data);const location_in_possible_locations=this.Location.Battle.GetPossibleLocations(card.Controller).includes(this.Location);if(card){if(location_in_possible_locations){this.append(card);card.classList.add("frontside")}else{alert("Can't be played here!");e.stopPropagation()}}})}}};customElements.define("location-owner",LocationOwner);})();