Skip to content

Commit

Permalink
Merge pull request terraforming-mars#2368 from kberg/moon8
Browse files Browse the repository at this point in the history
Moon #8 Add Mare Serenitatis Mine, which uses the Moon Road deferred Action, also enable some game pieces so I can test.
  • Loading branch information
kberg authored Jan 15, 2021
2 parents 1cad8b4 + 9413ee7 commit f28182b
Show file tree
Hide file tree
Showing 9 changed files with 138 additions and 7 deletions.
2 changes: 1 addition & 1 deletion server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -432,13 +432,13 @@ function createGame(req: http.IncomingMessage, res: http.ServerResponse): void {
aresExtension: gameReq.aresExtension,
aresHazards: true, // Not a runtime option.
politicalAgendasExtension: gameReq.politicalAgendasExtension,
moonExpansion: gameReq.moonExpansion,
promoCardsOption: gameReq.promoCardsOption,
communityCardsOption: gameReq.communityCardsOption,
solarPhaseOption: gameReq.solarPhaseOption,
removeNegativeGlobalEventsOption:
gameReq.removeNegativeGlobalEventsOption,
includeVenusMA: gameReq.includeVenusMA,
moonExpansion: false,

draftVariant: gameReq.draftVariant,
initialDraftVariant: gameReq.initialDraft,
Expand Down
2 changes: 2 additions & 0 deletions src/CardFinder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {VENUS_CARD_MANIFEST} from './cards/venusNext/VenusCardManifest';
import {COMMUNITY_CARD_MANIFEST} from './cards/community/CommunityCardManifest';
import {ARES_CARD_MANIFEST} from './cards/ares/AresCardManifest';
import {StandardProjectCard} from './cards/standardProjects/StandardProjectCard';
import {MOON_CARD_MANIFEST} from './cards/moon/MoonCardManifest';

export class CardFinder {
private static decks: undefined | Array<CardManifest>;
Expand All @@ -28,6 +29,7 @@ export class CardFinder {
TURMOIL_CARD_MANIFEST,
ARES_CARD_MANIFEST,
COMMUNITY_CARD_MANIFEST,
MOON_CARD_MANIFEST,
];
}
return CardFinder.decks;
Expand Down
2 changes: 2 additions & 0 deletions src/CardLoader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {ICardFactory} from './cards/ICardFactory';
import {Deck} from './Deck';
import {GameModule} from './GameModule';
import {GameOptions} from './Game';
import {MOON_CARD_MANIFEST} from './cards/moon/MoonCardManifest';

export class CardLoader {
private readonly gameOptions: GameOptions;
Expand All @@ -31,6 +32,7 @@ export class CardLoader {
[gameOptions.aresExtension, ARES_CARD_MANIFEST],
[gameOptions.promoCardsOption, PROMO_CARD_MANIFEST],
[gameOptions.communityCardsOption, COMMUNITY_CARD_MANIFEST],
[gameOptions.moonExpansion, MOON_CARD_MANIFEST],
];

this.manifests = manifests.filter((a) => a[0]).map((a) => a[1]);
Expand Down
4 changes: 2 additions & 2 deletions src/cards/base/RoboticWorkforce.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ export class RoboticWorkforce extends Card implements IProjectCard {
CardName.MARE_IMBRIUM_MINE,
CardName.MARE_NECTARIS_MINE,
CardName.MARE_NUBIUM_MINE,
// CardName.MARE_SERENITATIS_MINE,
CardName.MARE_SERENITATIS_MINE,
CardName.MARTIAN_INDUSTRIES,
CardName.MARTIAN_MEDIA_CENTER,
CardName.MEDICAL_LAB,
Expand Down Expand Up @@ -313,7 +313,7 @@ export class RoboticWorkforce extends Card implements IProjectCard {
new Updater(CardName.MARE_IMBRIUM_MINE, 0, 0, 1, 1, 0, 0),
new Updater(CardName.MARE_NECTARIS_MINE, 0, 0, 1, 0, 0, 0),
new Updater(CardName.MARE_NUBIUM_MINE, 0, 0, 0, 1, 0, 0),
// new Updater(CardName.MARE_SERENITATIS_MINE, 0, 0, 1, 1, 0, 0),
new Updater(CardName.MARE_SERENITATIS_MINE, 0, 0, 1, 1, 0, 0),
new Updater(CardName.MARTIAN_INDUSTRIES, 1, 0, 1, 0, 0, 0),
new Updater(CardName.MARTIAN_MEDIA_CENTER, 0, 2, 0, 0, 0, 0),
new Updater(CardName.MEDICAL_LAB, 0, Math.floor(player.getTagCount(Tags.BUILDING) / 2), 0, 0, 0, 0),
Expand Down
52 changes: 52 additions & 0 deletions src/cards/moon/MareSerenitatisMine.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import {CardName} from '../../CardName';
import {Player} from '../../Player';
import {CardType} from '../CardType';
import {Tags} from '../Tags';
import {CardRenderer} from '../render/CardRenderer';
import {Resources} from '../../Resources';
import {MoonSpaces} from '../../moon/MoonSpaces';
import {MoonExpansion} from '../../moon/MoonExpansion';
import {PlaceMoonRoadTile} from '../../moon/PlaceMoonRoadTile';
import {Units} from '../../Units';
import {SpaceType} from '../../SpaceType';
import {IProjectCard} from '../IProjectCard';
import {Card} from '../Card';

export class MareSerenitatisMine extends Card implements IProjectCard {
constructor() {
super({
name: CardName.MARE_SERENITATIS_MINE,
cardType: CardType.AUTOMATED,
tags: [Tags.MOON, Tags.BUILDING],
cost: 21,

metadata: {
description: 'Spend 2 titanium and 1 steel. Increase your steel production 1 step and your titanium production 1 step. ' +
'Place a mine ON THE RESERVED AREA and adjacent to it road tile. Raise Mining Rate 1 step and Logistic Rate 1 step.',
cardNumber: 'M04',
renderData: CardRenderer.builder((b) => {
b.minus().titanium(2).minus().steel(1).br;
b.production((pb) => pb.steel(1).titanium(1)).br;
b.moonMine().asterix().nbsp.moonRoad().asterix();
}),
},
});
}

public reserveUnits = Units.of({titanium: 2, steel: 1});

public play(player: Player) {
Units.deductUnits(this.reserveUnits, player);
player.addProduction(Resources.STEEL, 1);
player.addProduction(Resources.TITANIUM, 1);
MoonExpansion.addMineTile(player, MoonSpaces.MARE_SERENITATIS, this.name);
MoonExpansion.raiseMiningRate(player);
const moon = MoonExpansion.moonData(player.game).moon;
const spaces = moon.getAdjacentSpaces(moon.getSpace(MoonSpaces.MARE_SERENITATIS));
const availableRoadSpaces = spaces.filter((space) => {
return space.player === undefined && space.spaceType === SpaceType.LAND;
});
player.game.defer(new PlaceMoonRoadTile(player, 'Select a space next to Mare Serintatis to play a road', availableRoadSpaces));
return undefined;
}
}
6 changes: 3 additions & 3 deletions src/cards/moon/MoonCardManifest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ import {CardManifest} from '../CardManifest';
import {MareImbriumMine} from './MareImbriumMine';
import {MareNectarisMine} from './MareNectarisMine';
import {MareNubiumMine} from './MareNubiumMine';
// import {MareSerenitatisMine} from './MareSerenitatisMine';
import {MareSerenitatisMine} from './MareSerenitatisMine';
// import {MicrosingularityPlant} from './MicrosingularityPlant';
// import {MiningComplex} from './MiningComplex';
// import {MiningRobotsManufCenter} from './MiningRobotsManufCenter';
Expand Down Expand Up @@ -101,10 +101,10 @@ export const MOON_CARD_MANIFEST = new CardManifest({
projectCards: [
// These cards are done.
{cardName: CardName.MARE_NECTARIS_MINE, Factory: MareNectarisMine},
// // These cards have behavior and rendering.
{cardName: CardName.MARE_NUBIUM_MINE, Factory: MareNubiumMine},
{cardName: CardName.MARE_IMBRIUM_MINE, Factory: MareImbriumMine},
// {cardName: CardName.MARE_SERENITATIS_MINE, Factory: MareSerenitatisMine},
{cardName: CardName.MARE_SERENITATIS_MINE, Factory: MareSerenitatisMine},
// // These cards have behavior and rendering.
// {cardName: CardName.HABITAT_14, Factory: Habitat14},
// {cardName: CardName.GEODESIC_TENTS, Factory: GeodesicTents},
// {cardName: CardName.SPHERE_HABITATS, Factory: SphereHabitats},
Expand Down
4 changes: 4 additions & 0 deletions src/components/CreateGameForm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export interface CreateGameModel {
communityCardsOption: boolean;
aresExtension: boolean;
politicalAgendasExtension: AgendaStyle;
moonExpansion: boolean;
undoOption: boolean;
showTimers: boolean;
fastModeOption: boolean;
Expand Down Expand Up @@ -115,6 +116,7 @@ export const CreateGameForm = Vue.component('create-game-form', {
communityCardsOption: false,
aresExtension: false,
politicalAgendasExtension: AgendaStyle.STANDARD,
moonExpansion: false,
undoOption: false,
showTimers: false,
fastModeOption: false,
Expand Down Expand Up @@ -383,6 +385,7 @@ export const CreateGameForm = Vue.component('create-game-form', {
const communityCardsOption = component.communityCardsOption;
const aresExtension = component.aresExtension;
const politicalAgendasExtension = this.politicalAgendasExtension;
const moonExpansion = component.moonExpansion;
const undoOption = component.undoOption;
const showTimers = component.showTimers;
const fastModeOption = component.fastModeOption;
Expand Down Expand Up @@ -441,6 +444,7 @@ export const CreateGameForm = Vue.component('create-game-form', {
communityCardsOption,
aresExtension: aresExtension,
politicalAgendasExtension: politicalAgendasExtension,
moonExpansion: moonExpansion,
undoOption,
showTimers,
fastModeOption,
Expand Down
7 changes: 6 additions & 1 deletion src/moon/PlaceMoonRoadTile.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {ISpace} from '../boards/ISpace';
import {DeferredAction} from '../deferredActions/DeferredAction';
import {SelectSpace} from '../inputs/SelectSpace';
import {Player} from '../Player';
Expand All @@ -8,11 +9,14 @@ export class PlaceMoonRoadTile implements DeferredAction {
constructor(
public player: Player,
public title: string = 'Select a space on the Moon for a road tile.',
public spaces?: Array<ISpace>,
) {}

public execute() {
const moonData = MoonExpansion.moonData(this.player.game);
const spaces = moonData.moon.getAvailableSpacesOnLand(this.player);
const spaces = this.spaces !== undefined ?
this.spaces:
moonData.moon.getAvailableSpacesOnLand(this.player);

if (spaces.length === 0) {
return undefined;
Expand All @@ -23,6 +27,7 @@ export class PlaceMoonRoadTile implements DeferredAction {
(space) => {
MoonExpansion.addRoadTile(this.player, space.id);
MoonExpansion.raiseLogisticRate(this.player);
// TODO(kberg): do not raise production rate unless this is done with a standard project.
this.player.addProduction(Resources.MEGACREDITS, 1, this.player.game);
return undefined;
});
Expand Down
66 changes: 66 additions & 0 deletions tests/cards/MareSerenitatisMine.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import {Game} from '../../src/Game';
import {IMoonData} from '../../src/moon/IMoonData';
import {MoonExpansion} from '../../src/moon/MoonExpansion';
import {Player} from '../../src/Player';
import {setCustomGameOptions, TestPlayers} from '../TestingUtils';
import {MareSerenitatisMine} from '../../src/cards/moon/MareSerenitatisMine';
import {expect} from 'chai';
import {Resources} from '../../src/Resources';
import {PlaceMoonRoadTile} from '../../src/moon/PlaceMoonRoadTile';
import {MoonSpaces} from '../../src/moon/MoonSpaces';
import {TileType} from '../../src/TileType';

const MOON_OPTIONS = setCustomGameOptions({moonExpansion: true});

describe('MareSerenitatisMine', () => {
let game: Game;
let player: Player;
let moonData: IMoonData;
let card: MareSerenitatisMine;

beforeEach(() => {
player = TestPlayers.BLUE.newPlayer();
game = Game.newInstance('id', [player], player, MOON_OPTIONS);
moonData = MoonExpansion.moonData(game);
card = new MareSerenitatisMine();
});

it('can play', () => {
// TODO: Ensuring resources is going to require changes coming later.
});

it('play', () => {
player.titanium = 3;
player.steel = 3;
expect(player.getProduction(Resources.STEEL)).eq(0);
expect(player.getProduction(Resources.TITANIUM)).eq(0);
expect(player.getTerraformRating()).eq(14);
expect(moonData.miningRate).eq(0);

card.play(player);

expect(player.titanium).eq(1);
expect(player.steel).eq(2);
expect(player.getProduction(Resources.STEEL)).eq(1);
expect(player.getProduction(Resources.TITANIUM)).eq(1);
expect(player.getTerraformRating()).eq(15);
expect(moonData.miningRate).eq(1);

const mareSerenitatis = moonData.moon.getSpace(MoonSpaces.MARE_SERENITATIS);
expect(mareSerenitatis.player).eq(player);
expect(mareSerenitatis.tile!.tileType).eq(TileType.MOON_MINE);

const deferredAction = game.deferredActions.next() as PlaceMoonRoadTile;
const roadSpace = deferredAction.spaces![0];
expect(roadSpace.tile).is.undefined;
expect(roadSpace.player).is.undefined;
expect(moonData.logisticRate).eq(0);

deferredAction!.execute()!.cb(roadSpace);
expect(roadSpace.tile!.tileType).eq(TileType.MOON_ROAD);
expect(roadSpace.player).eq(player);
expect(moonData.logisticRate).eq(1);
expect(player.getTerraformRating()).eq(16);
});
});

0 comments on commit f28182b

Please sign in to comment.