import { Resources } from '../Resources' ; import { PartyName } from '../turmoil/parties/PartyName' ; import { CardRequirement , PartyCardRequirement , ProductionCardRequirement , TagCardRequirement } from './CardRequirement' ; import { RequirementType } from './RequirementType' ; import { Tags } from './Tags' ; import { Player } from '../Player' ; import { MAX_OCEAN_TILES , MAX_OXYGEN_LEVEL , MAX_TEMPERATURE , MAX_VENUS_SCALE , MIN_OXYGEN_LEVEL , MIN_TEMPERATURE , MIN_VENUS_SCALE , } from '../constants' ; export class CardRequirements { constructor ( public requirements ) { } public static builder ( f ) { const builder = new Builder ( ) ; f ( builder ) ; return builder . build ( ) ; } public getRequirementsText ( ) { const reqTexts = this . requirements . map ( ( req ) => req . getLabel ( ) ) ; if ( this . hasAny ( ) ) { reqTexts . unshift ( 'Any' ) ; } return reqTexts . join ( ' ' ) ; } public hasMax ( ) { return this . requirements . some ( ( req ) => req . isMax ) ; } public hasAny ( ) { return this . requirements . some ( ( req ) => req . isAny ) ; } public hasParty ( partyName ? ) { return this . requirements . some ( ( req ) => { if ( ! ( req instanceof PartyCardRequirement ) ) return false ; if ( partyName === undefined ) return true ; return req . party === partyName ; } ) ; } public hasPlantsRemoved ( ) { return this . requirements . some ( ( req ) => req . type === RequirementType . REMOVED_PLANTS ) ; } public satisfies ( player ) { const tags = [ ] ; this . requirements . forEach ( ( requirement ) => { if ( ( requirement . type === RequirementType . TAG ) && requirement . isAny !== true && requirement . isMax !== true ) { tags . push ( ( requirement as TagCardRequirement ) . tag ) ; } } ) ; if ( ! player . checkMultipleTagPresence ( tags ) ) { return false ; } return this . requirements . every ( ( requirement ) => requirement . satisfies ( player ) ) ; } } export type Options = { max ? : boolean ; all ? : boolean ; text ? : string ; } ; class Builder { private reqs : Array < CardRequirement > = [ ] ; public build ( ) { return new CardRequirements ( this . reqs ) ; } public oceans ( amount = 1 , options ? ) { const req = new CardRequirement ( RequirementType . OCEANS , amount , options ) ; if ( req . amount <= 0 || req . amount > MAX_OCEAN_TILES ) { throw new Error ( 'Ocean tiles must be above 0 and below ' + MAX_OCEAN_TILES ) ; } this . reqs . push ( req ) ; return this ; } public oxygen ( amount = 1 , options ? ) { const req = new CardRequirement ( RequirementType . OXYGEN , amount , options ) ; if ( req . amount < MIN_OXYGEN_LEVEL || req . amount > MAX_OXYGEN_LEVEL ) { throw new Error ( 'Oxygen must be above ' + MIN_OXYGEN_LEVEL + ' and below ' + MAX_OXYGEN_LEVEL ) ; } this . reqs . push ( req ) ; return this ; } public temperature ( amount = 1 , options ? ) { const req = new CardRequirement ( RequirementType . TEMPERATURE , amount , options ) ; if ( req . amount < MIN_TEMPERATURE || req . amount > MAX_TEMPERATURE ) { throw new Error ( 'Temperature must be above ' + MIN_TEMPERATURE + ' and below ' + MAX_TEMPERATURE ) ; } if ( req . amount % 2 !== 0 ) { throw new Error ( 'Temperature must be even' ) ; } this . reqs . push ( req ) ; return this ; } public venus ( amount = 1 , options ? ) { const req = new CardRequirement ( RequirementType . VENUS , amount , options ) ; if ( req . amount < MIN_VENUS_SCALE || req . amount > MAX_VENUS_SCALE ) { throw new Error ( 'Venus must be above ' + MIN_VENUS_SCALE + ' and below ' + MAX_VENUS_SCALE ) ; } this . reqs . push ( req ) ; return this ; } public tr ( amount = 1 , options ? ) { this . reqs . push ( new CardRequirement ( RequirementType . TR , amount , options ) ) ; return this ; } public chairman ( ) { this . reqs . push ( new CardRequirement ( RequirementType . CHAIRMAN ) ) ; return this ; } public resourceTypes ( amount = 1 , options ? ) { this . reqs . push ( new CardRequirement ( RequirementType . RESOURCE_TYPES , amount , options ) ) ; return this ; } public greeneries ( amount = 1 , options ? ) { this . reqs . push ( new CardRequirement ( RequirementType . GREENERIES , amount , options ) ) ; return this ; } public cities ( amount = 1 , options ? ) { this . reqs . push ( new CardRequirement ( RequirementType . CITIES , amount , options ) ) ; return this ; } public colonies ( amount = 1 , options ? ) { this . reqs . push ( new CardRequirement ( RequirementType . COLONIES , amount , options ) ) ; return this ; } public floaters ( amount = 1 , options ? ) { this . reqs . push ( new CardRequirement ( RequirementType . FLOATERS , amount , options ) ) ; return this ; } public partyLeaders ( amount = 1 , options ? ) { this . reqs . push ( new CardRequirement ( RequirementType . PARTY_LEADERS , amount , options ) ) ; return this ; } public tag ( tag , amount = 1 , options ? ) { this . reqs . push ( new TagCardRequirement ( tag , amount , options ) ) ; return this ; } public production ( resource , amount = 1 , options ? ) { this . reqs . push ( new ProductionCardRequirement ( resource , amount , options ) ) ; return this ; } public party ( party ) { this . reqs . push ( new PartyCardRequirement ( party ) ) ; return this ; } public plantsRemoved ( ) { this . reqs . push ( new CardRequirement ( RequirementType . REMOVED_PLANTS ) ) ; return this ; } public colonyRate ( amount = 1 , options ? ) { this . reqs . push ( new CardRequirement ( RequirementType . COLONY_RATE , amount , options ) ) ; return this ; } public miningRate ( amount = 1 , options ? ) { this . reqs . push ( new CardRequirement ( RequirementType . MINING_RATE , amount , options ) ) ; return this ; } public logisticRate ( amount = 1 , options ? ) { this . reqs . push ( new CardRequirement ( RequirementType . LOGISTIC_RATE , amount , options ) ) ; return this ; } public colonyTiles ( amount = 1 , options ? ) { this . reqs . push ( new CardRequirement ( RequirementType . COLONY_TILES , amount , options ) ) ; return this ; } public miningTiles ( amount = 1 , options ? ) { this . reqs . push ( new CardRequirement ( RequirementType . MINING_TILES , amount , options ) ) ; return this ; } public roadTiles ( amount = 1 , options ? ) { this . reqs . push ( new CardRequirement ( RequirementType . ROAD_TILES , amount , options ) ) ; return this ; } }