Socket
Socket
Sign inDemoInstall

@gaia-project/engine

Package Overview
Dependencies
6
Maintainers
2
Versions
272
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 4.8.42 to 4.8.43

7

dist/index.js

@@ -25,3 +25,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.MAX_SATELLITES = exports.Power = exports.stdBuildingValue = exports.federations = exports.parseLocation = exports.finalRankings = exports.gainFinalScoringVictoryPoints = exports.SpaceMap = exports.Reward = exports.tiles = exports.Event = exports.PlayerData = exports.Player = exports.BuildWarning = void 0;
exports.MAX_SATELLITES = exports.Power = exports.stdBuildingValue = exports.parseLocation = exports.finalRankings = exports.gainFinalScoringVictoryPoints = exports.SpaceMap = exports.Reward = exports.Event = exports.PlayerData = exports.Player = exports.BuildWarning = void 0;
const scoring_1 = require("./src/algorithms/scoring");

@@ -47,6 +47,2 @@ Object.defineProperty(exports, "finalRankings", { enumerable: true, get: function () { return scoring_1.finalRankings; } });

exports.Reward = reward_1.default;
const tiles_1 = __importDefault(require("./src/tiles"));
exports.tiles = tiles_1.default;
const federations_1 = __importDefault(require("./src/tiles/federations"));
exports.federations = federations_1.default;
var actions_1 = require("./src/actions");

@@ -120,4 +116,3 @@ Object.defineProperty(exports, "boardActions", { enumerable: true, get: function () { return actions_1.boardActions; } });

Object.defineProperty(exports, "finalScorings", { enumerable: true, get: function () { return scoring_2.finalScorings; } });
Object.defineProperty(exports, "roundScorings", { enumerable: true, get: function () { return scoring_2.roundScorings; } });
exports.default = engine_1.default;
//# sourceMappingURL=index.js.map

2

dist/package.json
{
"name": "@gaia-project/engine",
"version": "4.8.42",
"version": "4.8.43",
"description": "Javascript engine for project gaia",

@@ -5,0 +5,0 @@ "main": "dist/index.js",

@@ -16,3 +16,3 @@ "use strict";

{
building: enums_1.Building.Mine,
buildings: [enums_1.Building.Mine],
domestic: true,

@@ -24,3 +24,3 @@ free: true,

{
building: enums_1.Building.Mine,
buildings: [enums_1.Building.Mine],
base: [],

@@ -31,3 +31,3 @@ bonus: reward_1.default.parse("1c,1o"),

{
building: enums_1.Building.TradingStation,
buildings: [enums_1.Building.TradingStation],
base: reward_1.default.parse("5c"),

@@ -37,3 +37,3 @@ bonus: reward_1.default.parse("3c,1pw"),

{
building: enums_1.Building.ResearchLab,
buildings: [enums_1.Building.ResearchLab],
base: reward_1.default.parse("2k"),

@@ -43,3 +43,3 @@ bonus: reward_1.default.parse("1k"),

{
building: enums_1.Building.Academy1,
buildings: [enums_1.Building.Academy1, enums_1.Building.Academy2],
base: reward_1.default.parse("2k"),

@@ -50,3 +50,3 @@ bonus: reward_1.default.parse("1k"),

{
building: enums_1.Building.PlanetaryInstitute,
buildings: [enums_1.Building.PlanetaryInstitute],
base: reward_1.default.parse("1t,2pw"),

@@ -56,3 +56,3 @@ bonus: reward_1.default.parse("4pw"),

{
building: enums_1.Building.Colony,
buildings: [enums_1.Building.Colony],
base: reward_1.default.parse("3vp"),

@@ -171,3 +171,3 @@ bonus: reward_1.default.parse("2vp"),

const domestic = h.data.player === player;
const option = exports.tradeOptions.find((o) => o.building === building && !!o.domestic === domestic);
const option = exports.tradeOptions.find((o) => o.buildings.includes(building) && !!o.domestic === domestic);
if (option) {

@@ -174,0 +174,0 @@ const cost = tradeCost(guest, option);

@@ -12,3 +12,2 @@ "use strict";

const enums_1 = require("./enums");
const events_1 = __importDefault(require("./events"));
const faction_boards_1 = require("./faction-boards");

@@ -661,5 +660,4 @@ const map_1 = __importDefault(require("./map"));

get currentRoundScoringEvents() {
const roundScoringTile = this.tiles.scorings.round[this.round - 1];
const roundScoring = scoring_1.roundScorings[roundScoringTile];
return roundScoring && events_1.default.parse(roundScoring, `round${this.round}`);
const tile = this.tiles.scorings.round[this.round - 1];
return tile && scoring_1.roundScoringEvents(tile, this.round);
}

@@ -666,0 +664,0 @@ changePhase(phase) {

@@ -60,4 +60,8 @@ "use strict";

}
get federations() {
var _a;
return (_a = this.data.federations) !== null && _a !== void 0 ? _a : [];
}
belongsToFederationOf(player) {
return this.data.federations && this.data.federations.includes(player);
return this.federations.includes(player);
}

@@ -64,0 +68,0 @@ addToFederationOf(player) {

@@ -9,4 +9,3 @@ "use strict";

const enums_1 = require("../enums");
const reward_1 = __importDefault(require("../reward"));
const federations_1 = __importDefault(require("../tiles/federations"));
const federations_1 = require("../tiles/federations");
function moveChooseFederationTile(engine, command, player, federation) {

@@ -16,3 +15,3 @@ const { tiles, rescore } = command.data;

if (rescore) {
engine.player(player).gainRewards(reward_1.default.parse(federations_1.default[federation]), enums_1.BoardAction.Qic2);
engine.player(player).gainRewards(federations_1.federationRewards(federation), enums_1.BoardAction.Qic2);
}

@@ -19,0 +18,0 @@ else {

@@ -27,3 +27,3 @@ "use strict";

}
engine.player(player).gainTechTile(tileAvailable.tile, tileAvailable.pos);
engine.player(player).gainTechTile(tileAvailable);
engine.tiles.techs[pos].count -= 1;

@@ -30,0 +30,0 @@ // AFTER gaining the tech tile (as green federation can be flipped and lock research tracks)

"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {

@@ -43,6 +24,6 @@ return (mod && mod.__esModule) ? mod : { "default": mod };

const reward_1 = __importDefault(require("./reward"));
const boosters_1 = __importDefault(require("./tiles/boosters"));
const federations_1 = __importStar(require("./tiles/federations"));
const boosters_1 = require("./tiles/boosters");
const federations_1 = require("./tiles/federations");
const scoring_1 = require("./tiles/scoring");
const techs_1 = __importStar(require("./tiles/techs"));
const techs_1 = require("./tiles/techs");
const utils_1 = require("./utils");

@@ -102,11 +83,10 @@ // 25 satellites total

get income() {
return reward_1.default.toString(reward_1.default.merge([].concat(...this.events[enums_1.Operator.Income].map((event) => event.rewards))), true);
return reward_1.default.toString(this.incomeRewards, true);
}
get incomeRewards() {
return reward_1.default.merge([].concat(...this.events[enums_1.Operator.Income].map((event) => event.rewards)));
}
resourceIncome(resource) {
const i = this.income;
const index = i.search(new RegExp("[0-9]+" + resource));
if (index < 0) {
return 0;
}
return parseInt(i.substr(index));
var _a, _b;
return (_b = (_a = this.incomeRewards.find((r) => r.type === resource)) === null || _a === void 0 ? void 0 : _a.count) !== null && _b !== void 0 ? _b : 0;
}

@@ -362,4 +342,3 @@ get actions() {

if (event.operator === enums_1.Operator.Once) {
const times = this.eventConditionCount(event.condition);
this.gainRewards(event.rewards.map((reward) => new reward_1.default(reward.count * times, reward.type)), event.source);
this.gainRewards(this.eventConditionRewards(event), event.source);
}

@@ -388,5 +367,4 @@ }

removeRoundBoosterEvents(type) {
let eventList = events_1.default.parse(boosters_1.default[this.data.tiles.booster], this.data.tiles.booster);
eventList = eventList.filter((ev) => (type && ev.operator === enums_1.Operator.Income) || (!type && ev.operator !== enums_1.Operator.Income));
for (const event of eventList) {
const events = boosters_1.boosterEvents(this.data.tiles.booster).filter((ev) => (type && ev.operator === enums_1.Operator.Income) || (!type && ev.operator !== enums_1.Operator.Income));
for (const event of events) {
this.removeEvent(event);

@@ -553,13 +531,13 @@ }

this.data.tiles.booster = roundBooster;
this.loadEvents(events_1.default.parse(boosters_1.default[roundBooster], roundBooster));
this.loadEvents(boosters_1.boosterEvents(roundBooster));
}
gainTechTile(tile, pos) {
const advanced = techs_1.isAdvanced(pos);
gainTechTile(chooseTechTile) {
const advanced = techs_1.isAdvanced(chooseTechTile.pos);
if (advanced) {
this.data.removeGreenFederation();
}
this.data.tiles.techs.push({ tile, pos, enabled: true });
this.loadEvents(events_1.default.parse(techs_1.default[tile], !advanced ? `tech-${pos}` : pos));
this.data.tiles.techs.push({ ...chooseTechTile, enabled: true });
this.loadEvents(techs_1.techTileEvents(chooseTechTile));
// resets federationCache if Special PA->4pw
if (tile === enums_1.TechTile.Tech3) {
if (chooseTechTile.tile === enums_1.TechTile.Tech3) {
this.federationCache = null;

@@ -571,3 +549,3 @@ }

tile.enabled = false;
const events = events_1.default.parse(techs_1.default[tile.tile], `tech-${pos}`);
const events = techs_1.techTileEvents(tile);
this.removeEvents(events);

@@ -625,8 +603,8 @@ if (events.some((event) => event.operator === enums_1.Operator.FourPowerBuildings)) {

// this is for pass tile income (e.g. round boosters, adv tiles)
return this.events[enums_1.Operator.Pass].map((event) => {
const times = this.eventConditionCount(event.condition);
const rewards = event.rewards.map((reward) => new reward_1.default(reward.count * times, reward.type));
return new events_1.default(rewards.join(","), event.source);
});
return this.events[enums_1.Operator.Pass].map((event) => new events_1.default(this.eventConditionRewards(event).join(","), event.source));
}
eventConditionRewards(event) {
const times = this.eventConditionCount(event.condition);
return event.rewards.map((reward) => new reward_1.default(reward.count * times, reward.type));
}
receivePassIncome() {

@@ -717,3 +695,3 @@ for (const e of this.passIncomeEvents()) {

});
this.gainRewards(reward_1.default.parse(federations_1.default[federation]), enums_1.Command.FormFederation);
this.gainRewards(federations_1.federationRewards(federation), enums_1.Command.FormFederation);
this.receiveTriggerIncome(enums_1.Condition.Federation);

@@ -720,0 +698,0 @@ }

@@ -42,3 +42,3 @@ "use strict";

toStringWithZero() {
return `${this.count}${this.type}`;
return this.count === 1 ? this.type.toString() : `${this.count}${this.type}`;
}

@@ -71,3 +71,2 @@ toJSON() {

static toString(rewards, sorted = true) {
// const sortOrder = ['c', 'o', 'k', 'q', 'pw'];
const sortOrder = ["pw", "q", "k", "o", "c"];

@@ -74,0 +73,0 @@ if (sorted) {

"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.boosterEvents = void 0;
const enums_1 = require("../enums");
exports.default = {
const events_1 = __importDefault(require("../events"));
const boosterSpec = {
[enums_1.Booster.Booster1]: ["+k", "+o"],

@@ -16,2 +21,6 @@ [enums_1.Booster.Booster2]: ["+o", "+2t"],

};
function boosterEvents(booster) {
return events_1.default.parse(boosterSpec[booster], booster);
}
exports.boosterEvents = boosterEvents;
//# sourceMappingURL=boosters.js.map
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.isGreen = void 0;
exports.isGreen = exports.federationRewards = void 0;
const enums_1 = require("../enums");
exports.default = {
const reward_1 = __importDefault(require("../reward"));
const federationSpec = {
[enums_1.Federation.Fed1]: "12vp",

@@ -14,2 +18,6 @@ [enums_1.Federation.Fed2]: "8vp,q",

};
function federationRewards(federation) {
return reward_1.default.parse(federationSpec[federation]);
}
exports.federationRewards = federationRewards;
function isGreen(federation) {

@@ -16,0 +24,0 @@ return federation !== enums_1.Federation.Fed1;

"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.finalScorings = exports.roundScorings = void 0;
exports.finalScorings = exports.roundScoringEvents = void 0;
const enums_1 = require("../enums");
const events_1 = __importDefault(require("../events"));
const roundScorings = {

@@ -17,4 +21,8 @@ [enums_1.ScoringTile.Score1]: ["step >> 2vp"],

};
exports.roundScorings = roundScorings;
const finalScorings = {
function roundScoringEvents(tile, round) {
const roundScoring = roundScorings[tile];
return events_1.default.parse(roundScoring, `round${round}`);
}
exports.roundScoringEvents = roundScoringEvents;
exports.finalScorings = {
[enums_1.FinalTile.Structure]: { condition: enums_1.Condition.Structure, neutralPlayer: 11 },

@@ -27,3 +35,2 @@ [enums_1.FinalTile.StructureFed]: { condition: enums_1.Condition.StructureFed, neutralPlayer: 10 },

};
exports.finalScorings = finalScorings;
//# sourceMappingURL=scoring.js.map
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.isAdvanced = void 0;
exports.isAdvanced = exports.techTileRewards = exports.techTileEvents = exports.techTileEventWithSource = void 0;
const enums_1 = require("../enums");
exports.default = {
const events_1 = __importDefault(require("../events"));
const techTileSpec = {
[enums_1.TechTile.Tech1]: ["o,q"],

@@ -32,2 +36,15 @@ [enums_1.TechTile.Tech2]: ["pt > k"],

};
function techTileEventWithSource(tile, source) {
return events_1.default.parse(techTileSpec[tile], source);
}
exports.techTileEventWithSource = techTileEventWithSource;
function techTileEvents(chooseTechTile) {
const pos = chooseTechTile.pos;
return techTileEventWithSource(chooseTechTile.tile, isAdvanced(pos) ? pos : `tech-${pos}`);
}
exports.techTileEvents = techTileEvents;
function techTileRewards(tile) {
return techTileEventWithSource(tile, null).flatMap((e) => e.rewards);
}
exports.techTileRewards = techTileRewards;
function isAdvanced(pos) {

@@ -34,0 +51,0 @@ return pos.startsWith("adv");

@@ -9,4 +9,2 @@ import { finalRankings, gainFinalScoringVictoryPoints } from "./src/algorithms/scoring";

import Reward from "./src/reward";
import tiles from "./src/tiles";
import federations from "./src/tiles/federations";

@@ -79,3 +77,3 @@ export { boardActions, FreeAction, freeActionConversions, ResourceConversion } from "./src/actions";

export { AvailableSetupOption, SetupType } from "./src/setup";
export { finalScorings, roundScorings } from "./src/tiles/scoring";
export { finalScorings } from "./src/tiles/scoring";
export {

@@ -88,3 +86,2 @@ BrainstoneDest,

Event,
tiles,
Reward,

@@ -96,3 +93,2 @@ SpaceMap,

parseLocation,
federations,
stdBuildingValue,

@@ -99,0 +95,0 @@ Power,

{
"name": "@gaia-project/engine",
"version": "4.8.42",
"version": "4.8.43",
"description": "Javascript engine for project gaia",

@@ -5,0 +5,0 @@ "main": "dist/index.js",

@@ -5,31 +5,396 @@ import { expect } from "chai";

describe("Trade ships", () => {
const moves = [
"init 2 Pleasant-barrel-3642",
"p1 faction ambas",
"p2 faction firaks (0/0/0/0 ⇒ 2/4/0/0)",
"ambas build m 7B2",
"firaks build m 7A6",
"firaks build m 2A10",
"ambas build m 2B3",
"firaks booster booster9",
"ambas booster booster5 (2/4/0/0 ⇒ 0/6/0/0)",
"ambas build ts 7B2.",
"firaks charge 1pw (0/4/2/0 ⇒ 0/3/3/0)",
"firaks build tradeShip 7B3.",
"ambas pass booster2 returning booster5",
"firaks pass booster6 returning booster9",
"ambas pass booster9 returning booster2",
];
describe("trade costs", () => {
const moves = [
"init 2 Pleasant-barrel-3642",
"p1 faction ambas",
"p2 faction firaks (0/0/0/0 ⇒ 2/4/0/0)",
"ambas build m 7B2",
"firaks build m 7A6",
"firaks build m 2A10",
"ambas build m 2B3",
"firaks booster booster9",
"ambas booster booster5 (2/4/0/0 ⇒ 0/6/0/0)",
"ambas build ts 7B2.",
"firaks charge 1pw (0/4/2/0 ⇒ 0/3/3/0)",
"firaks build tradeShip 7B3.",
"ambas pass booster2 returning booster5",
"firaks pass booster6 returning booster9",
"ambas pass booster9 returning booster2",
];
it("can trade when the trade cost is fulfilled", () => {
const engine = new Engine(moves, { frontiers: true });
expect(() => engine.move("firaks move tradeShip 7B3 7B3 trade 7B2.")).to.not.throw();
it("can trade when the trade cost is fulfilled", () => {
const engine = new Engine(moves, { frontiers: true });
expect(() => engine.move("firaks move tradeShip 7B3 7B3 trade 7B2.")).to.not.throw();
});
it("can not trade when the trade cost is not fulfilled", () => {
const engine = new Engine(moves, { frontiers: true });
expect(() =>
engine.move("spend 3pw for 1o (0/3/3/0 ⇒ 3/3/0/0). firaks move tradeShip 7B3 7B3 trade 7B2.")
).to.throw();
});
});
it("can not trade when the trade cost is not fulfilled", () => {
const engine = new Engine(moves, { frontiers: true });
expect(() =>
engine.move("spend 3pw for 1o (0/3/3/0 ⇒ 3/3/0/0). firaks move tradeShip 7B3 7B3 trade 7B2.")
).to.throw();
it("academy", function () {
this.timeout(5000);
const moves = [
"init 4 Epic-way-5435",
"p4 rotate 0x0 3 -6x10 3 -1x8 4 2x3 3 -8x7 2 -2x-3 2 5x-2 4 3x-5 5",
"p1 faction ambas",
"p2 faction xenos",
"p3 faction hadsch-hallas",
"p4 faction itars (0/0/0/0 ⇒ 4/4/0/0)",
"ambas build m 7A9",
"xenos build m 5A6",
"hadsch-hallas build m 7B4",
"itars build m 3B2",
"itars build m 9A8",
"hadsch-hallas build m 10A11",
"xenos build m 10B1",
"ambas build m 6B1",
"xenos build m 3A6",
"itars booster booster5",
"hadsch-hallas booster booster4",
"xenos booster booster1",
"ambas booster booster10",
"itars income 2pw (4/4/0/0 ⇒ 3/6/0/0)",
"ambas build ts 7A9.",
"xenos charge 1pw (2/4/0/0 ⇒ 1/5/0/0)",
"hadsch-hallas charge 1pw (2/4/0/0 ⇒ 1/5/0/0)",
"itars charge 1pw (3/6/0/0 ⇒ 2/7/0/0)",
"xenos build ts 10B1.",
"hadsch-hallas charge 1pw (1/5/0/0 ⇒ 0/6/0/0)",
"hadsch-hallas build ts 7B4.",
"ambas charge 2pw (2/4/0/0 ⇒ 0/6/0/0)",
"itars special range+3. build m 6B5.",
"ambas charge 1pw (0/6/0/0 ⇒ 0/5/1/0)",
"ambas build lab 7A9. tech nav. up nav (1 ⇒ 2).",
"xenos charge 1pw (1/5/0/0 ⇒ 0/6/0/0)",
"hadsch-hallas charge 2pw (0/6/0/0 ⇒ 0/4/2/0)",
"itars charge 1pw (2/7/0/0 ⇒ 1/8/0/0)",
"xenos build lab 10B1. tech nav. up nav (0 ⇒ 1).",
"hadsch-hallas charge 1pw (0/4/2/0 ⇒ 0/3/3/0)",
"hadsch-hallas special step. build m 10A0.",
"xenos charge 2pw (0/6/0/0 ⇒ 0/4/2/0)",
"itars build ts 6B5.",
"ambas charge 1pw (0/5/1/0 ⇒ 0/4/2/0)",
"ambas build m 7B0.",
"xenos charge 1pw (0/4/2/0 ⇒ 0/3/3/0)",
"hadsch-hallas charge 2pw (0/3/3/0 ⇒ 0/1/5/0)",
"xenos up nav (1 ⇒ 2).",
"hadsch-hallas action power3. (0/1/5/0 ⇒ 4/1/1/0)",
"itars up gaia (0 ⇒ 1).",
"ambas build m 7B2.",
"hadsch-hallas charge 2pw (4/1/1/0 ⇒ 2/3/1/0)",
"xenos action power6. build m 5A7. (0/3/3/0 ⇒ 3/3/0/0)",
"hadsch-hallas build lab 7B4. tech dip. up dip (0 ⇒ 1).",
"ambas charge 2pw (0/4/2/0 ⇒ 0/2/4/0)",
"itars burn 3. action power7. (1/8/0/0 ⇒ 6/2/0/3)",
"ambas action power4. (0/2/4/0 ⇒ 4/2/0/0)",
"xenos build m 10B4.",
"hadsch-hallas charge 1pw (2/3/1/0 ⇒ 1/4/1/0)",
"hadsch-hallas build tradeShip 10B0.",
"itars build gf 6A9 using area1: 6. (6/2/0/3 ⇒ 0/2/0/9)",
"ambas special 4pw. (4/2/0/0 ⇒ 0/6/0/0)",
"xenos build m 5B5.",
"hadsch-hallas build tradeShip 7B5.",
"itars build PI 6B5.",
"ambas charge 1pw (0/6/0/0 ⇒ 0/5/1/0)",
"ambas up eco (0 ⇒ 1).",
"xenos special 4pw. (3/3/0/0 ⇒ 0/5/1/0)",
"hadsch-hallas up dip (1 ⇒ 2).",
"itars burn 1. spend 1pw for 1c. build tradeShip 3A4. (0/2/0/9 ⇒ 1/0/0/10)",
"ambas pass booster6 returning booster10",
"xenos pass booster8 returning booster1",
"hadsch-hallas pass booster1 returning booster4",
"itars pass booster10 returning booster5",
"itars income 1t. income 4pw (1/0/0/10 ⇒ 1/0/2/10)",
"itars spend 4tg for tech. tech dip. up dip (0 ⇒ 1). spend 4tg for tech. tech eco. up eco (0 ⇒ 1) (1/0/2/10 ⇒ 3/0/2/0)",
"ambas build tradeShip 7B5.",
"xenos special 4pw. (0/5/1/0 ⇒ 0/1/5/0)",
"hadsch-hallas move tradeShip 10B0 10C trade 10B1. (0/4/2/0 ⇒ 2/4/0/0)",
"itars build m 6A9.",
"hadsch-hallas charge 1pw (2/4/0/0 ⇒ 1/5/0/0)",
"ambas special 4pw. (0/5/1/0 ⇒ 0/1/5/0)",
"xenos action power4. (0/1/5/0 ⇒ 4/1/1/0)",
"hadsch-hallas up dip (2 ⇒ 3). (1/5/0/0 ⇒ 0/4/2/0)",
"itars move tradeShip 3A4 7A8 trade 7A9. (3/0/2/0 ⇒ 5/0/0/0)",
"ambas action power3. (0/1/5/0 ⇒ 4/1/1/0)",
"xenos build m 6A8.",
"hadsch-hallas charge 1pw (0/4/2/0 ⇒ 0/3/3/0)",
"itars charge 3pw (5/0/0/0 ⇒ 2/3/0/0)",
"hadsch-hallas action power6. build m 1B1. (0/3/3/0 ⇒ 3/3/0/0)",
"itars spend 1o for 1t. build gf 8A3 using area1: 3, area2: 3. (2/3/0/0 ⇒ 0/0/0/6)",
"ambas build ac1 7A9. tech dip. up dip (0 ⇒ 1).",
"xenos charge 1pw (4/1/1/0 ⇒ 3/2/1/0)",
"hadsch-hallas charge 2pw (3/3/0/0 ⇒ 1/5/0/0)",
"xenos build ts 10B4.",
"hadsch-hallas charge 1pw (1/5/0/0 ⇒ 0/6/0/0)",
"hadsch-hallas build ts 10A0.",
"xenos charge 2pw (3/2/1/0 ⇒ 1/4/1/0)",
"itars pass booster2 returning booster10",
"ambas build tradeShip 6A1.",
"xenos build ts 5A6.",
"ambas charge 3pw (4/1/1/0 ⇒ 1/4/1/0)",
"hadsch-hallas burn 1. move tradeShip 7B5 7C trade 7B2. (0/6/0/0 ⇒ 1/4/0/0)",
"ambas pass booster5 returning booster6",
"xenos up terra (0 ⇒ 1).",
"hadsch-hallas build lab 10A0. tech free1. up dip (3 ⇒ 4).",
"xenos charge 2pw (1/4/1/0 ⇒ 0/4/2/0)",
"xenos pass booster4 returning booster8",
"hadsch-hallas pass booster6 returning booster1",
"itars income 2t. income 4pw. income 1t. income 1pw (0/0/0/6 ⇒ 1/1/2/6)",
"itars spend 4tg for tech. tech gaia. up gaia (1 ⇒ 2) (1/1/2/6 ⇒ 6/1/2/0)",
"itars build m 8A3.",
"xenos charge 1pw (0/4/2/0 ⇒ 0/3/3/0)",
"hadsch-hallas charge 2pw (0/2/3/0 ⇒ 0/0/5/0)",
"ambas move tradeShip 7B5 7C trade 7B0.",
"xenos action power7. (0/3/3/0 ⇒ 5/3/0/0)",
"hadsch-hallas action power3. (0/0/5/0 ⇒ 4/0/1/0)",
"itars build gf 9A7 using area1: 6. (6/1/2/0 ⇒ 0/1/2/6)",
"ambas up dip (1 ⇒ 2).",
"xenos build PI 10B4.",
"hadsch-hallas charge 1pw (4/0/1/0 ⇒ 3/1/1/0)",
"hadsch-hallas move tradeShip 7C 7A10 trade 5A6. (3/1/1/0 ⇒ 2/3/0/0)",
"itars build ts 6A9.",
"xenos charge 1pw (5/3/0/0 ⇒ 4/4/0/0)",
"hadsch-hallas charge 2pw (2/3/0/0 ⇒ 0/5/0/0)",
"ambas move tradeShip 6A1 6A1 trade 9A8. (0/3/3/0 ⇒ 2/3/1/0)",
"xenos federation 10A1,10B1,10B4,10C,6A8 fed5 using area1: 2. (4/4/0/0 ⇒ 2/4/0/0)",
"hadsch-hallas build ts 10A11.",
"xenos charge 3pw (2/4/0/0 ⇒ 0/5/1/0)",
"itars federation 6A9,6B5,8A3 fed3. (0/1/2/6 ⇒ 2/1/2/6)",
"ambas special 4pw. (2/3/1/0 ⇒ 0/3/3/0)",
"xenos special 4pw. (0/5/1/0 ⇒ 0/1/5/0)",
"hadsch-hallas build PI 10A11.",
"xenos charge 1pw (0/1/5/0 ⇒ 0/0/6/0)",
"itars up nav (0 ⇒ 1).",
"ambas special range+3. build m 1B5.",
"hadsch-hallas charge 1pw (0/5/0/0 ⇒ 0/4/1/0)",
"xenos action power6. build m 8B2. (0/0/6/0 ⇒ 3/0/3/0)",
"hadsch-hallas charge 3pw (0/4/1/0 ⇒ 0/1/4/0)",
"itars charge 2pw (2/1/2/6 ⇒ 0/3/2/6)",
"hadsch-hallas action power4. (0/1/4/0 ⇒ 4/1/0/0)",
"itars move tradeShip 7A8 7B3 trade 7B2. (0/3/2/6 ⇒ 2/3/0/6)",
"ambas build ts 7B0.",
"xenos charge 2pw (3/0/3/0 ⇒ 1/2/3/0)",
"hadsch-hallas charge 2pw (4/1/0/0 ⇒ 2/3/0/0)",
"itars charge 1pw (2/3/0/6 ⇒ 1/4/0/6)",
"xenos special step. build m 9A2.",
"hadsch-hallas spend 3c for 1o. spend 1o for 1t. burn 1. move tradeShip 10C 10B5 trade 10B4. (2/3/0/0 ⇒ 0/1/5/0)",
"itars burn 2. spend 1pw for 1c. build m 4A1. (1/4/0/6 ⇒ 2/0/1/8)",
"xenos charge 1pw (1/2/3/0 ⇒ 0/3/3/0)",
"ambas pass booster10 returning booster5",
"xenos spend 3pw for 1o. build m 1A9. (0/3/3/0 ⇒ 3/3/0/0)",
"ambas charge 1pw (0/3/3/0 ⇒ 0/2/4/0)",
"hadsch-hallas spend 3c for 1o. spend 4c for 1q. action power2. build m 8B4. (0/1/5/0 ⇒ 5/1/0/0)",
"xenos charge 1pw (3/3/0/0 ⇒ 2/4/0/0)",
"itars pass booster8 returning booster2",
"xenos pass booster2 returning booster4",
"hadsch-hallas up terra (0 ⇒ 1).",
"hadsch-hallas build ts 8B4.",
"xenos charge 1pw (2/4/0/0 ⇒ 1/5/0/0)",
"hadsch-hallas federation 10A0,10A11,8A5,8B3,8B4 fed5 using area1: 2. (5/1/0/0 ⇒ 3/1/0/0)",
"hadsch-hallas spend 12c for 3q. action qic2. fedtile fed5.",
"hadsch-hallas spend 4c for 1q. spend 3c for 1o. build m 1A6.",
"hadsch-hallas pass booster4 returning booster6",
"itars income 4pw. income 1t. income 1pw (2/0/1/8 ⇒ 1/1/3/8)",
"xenos income 4pw (1/5/0/0 ⇒ 2/3/3/0)",
"hadsch-hallas income 1t (3/1/0/0 ⇒ 0/1/4/0)",
"itars spend 4tg for tech. tech nav. up nav (1 ⇒ 2). spend 4tg for tech. tech free2. up gaia (2 ⇒ 3) (1/1/3/8 ⇒ 0/0/5/0)",
"ambas action power6. build m 3A3. (0/0/6/0 ⇒ 3/0/3/0)",
"xenos charge 2pw (2/3/3/0 ⇒ 0/5/3/0)",
"hadsch-hallas charge 1pw (0/1/4/0 ⇒ 0/0/5/0)",
"itars action power7. (0/0/5/0 ⇒ 5/0/2/0)",
"xenos special 4pw. (0/5/3/0 ⇒ 0/1/7/0)",
"hadsch-hallas spend 12c for 3q. action qic2. fedtile fed5. spend 1pw for 1c. (0/0/5/0 ⇒ 1/0/4/0)",
"ambas build PI 7B0.",
"xenos charge 1pw (0/1/7/0 ⇒ 0/0/8/0)",
"hadsch-hallas charge 2pw (1/0/4/0 ⇒ 0/0/5/0)",
"itars charge 1pw (5/0/2/0 ⇒ 4/1/2/0)",
"itars build m 3B5.",
"xenos action power4. (0/0/8/0 ⇒ 4/0/4/0)",
"hadsch-hallas action power3. (0/0/5/0 ⇒ 4/0/1/0)",
"ambas federation 3A3,7A9,7B0,7B5 fed6 using area1: 1. (3/0/3/0 ⇒ 2/0/3/0)",
"itars build gf 3A0 using area1: 4. (4/1/2/0 ⇒ 0/1/2/4)",
"xenos build lab 5A6. tech free2. up nav (2 ⇒ 3). (4/0/4/0 ⇒ 1/3/4/0)",
"ambas charge 3pw (2/0/3/0 ⇒ 0/1/4/0)",
"hadsch-hallas up dip (4 ⇒ 5).",
"ambas action power5. (0/1/4/0 ⇒ 4/1/0/0)",
"itars build m 9A7.",
"ambas charge 1pw (4/1/0/0 ⇒ 3/2/0/0)",
"xenos up nav (3 ⇒ 4).",
"hadsch-hallas special step. build m 1A5.",
"ambas up dip (2 ⇒ 3). (3/2/0/0 ⇒ 0/5/0/0)",
"itars build ts 4A1.",
"xenos charge 1pw (1/3/4/0 ⇒ 0/4/4/0)",
"xenos action qic3.",
"hadsch-hallas move tradeShip 10B5 10A1 trade 6A8.",
"ambas up dip (3 ⇒ 4).",
"itars spend 1pw for 1c. special 4pw. spend 3pw for 1o. (0/1/2/4 ⇒ 3/0/0/4)",
"xenos build ac1 5A6. tech adv-nav. cover free2. up terra (1 ⇒ 2).",
"ambas decline 3pw",
"hadsch-hallas build ac1 7B4. tech free2. up eco (1 ⇒ 2).",
"itars charge 1pw (3/0/0/4 ⇒ 2/1/0/4)",
"ambas charge 3pw (0/5/0/0 ⇒ 0/2/3/0)",
"ambas move tradeShip 7C 7B5 trade 7B4. (0/2/3/0 ⇒ 1/2/2/0)",
"itars build lab 4A1. tech free1. up nav (2 ⇒ 3). (2/1/0/4 ⇒ 0/2/1/4)",
"xenos charge 1pw (0/4/4/0 ⇒ 0/3/5/0)",
"xenos spend 1pw for 1c. pass booster6 returning booster2 (0/3/5/0 ⇒ 1/3/4/0)",
"hadsch-hallas build ts 1B1.",
"ambas charge 1pw (1/2/2/0 ⇒ 0/3/2/0)",
"ambas up nav (2 ⇒ 3). (0/3/2/0 ⇒ 0/0/5/0)",
"itars burn 1. move tradeShip 7B3 7A11 trade 7B0. (0/2/1/4 ⇒ 1/2/0/5)",
"hadsch-hallas federation 1A1,1A5,1A6,1B1,1B2,7A8,7B4 fed5 using area1: 3. (4/0/1/0 ⇒ 1/0/1/0)",
"ambas action power2. build m 2B3. (0/0/5/0 ⇒ 5/0/0/0)",
"itars spend 1q for 1o. spend 1o for 1t. build gf 6A5 using area1: 2, area2: 2. (1/2/0/5 ⇒ 0/0/0/9)",
"hadsch-hallas move tradeShip 7A10 7A10 trade 7A9. spend 1pw for 1c. (1/0/1/0 ⇒ 2/0/0/0)",
"ambas build m 2B0.",
"itars pass booster2 returning booster8",
"hadsch-hallas up eco (2 ⇒ 3). spend 1pw for 1c. (2/0/0/0 ⇒ 1/1/0/0)",
"ambas special 4pw. (5/0/0/0 ⇒ 1/4/0/0)",
"hadsch-hallas spend 3c for 1o. build tradeShip 1B0.",
"ambas special swap-PI (from 7B0). swap-PI 6B1 (from 7B0).",
"hadsch-hallas spend 3c for 1o. spend 1o for 1t. pass booster8 returning booster4 (1/1/0/0 ⇒ 2/1/0/0)",
"ambas burn 1. move tradeShip 6A1 6B4 trade 6A8. (1/4/0/0 ⇒ 2/2/0/0)",
"ambas pass booster4 returning booster10",
"itars income 2t. income 4pw. income 1t. income 1pw (0/0/0/9 ⇒ 1/1/2/9)",
"hadsch-hallas income 1t (2/1/0/0 ⇒ 0/0/4/0)",
"ambas income 2t (2/2/0/0 ⇒ 0/2/4/0)",
"itars spend 4tg for tech. tech free3. up nav (3 ⇒ 4). decline tech (1/1/2/9 ⇒ 6/1/2/0)",
"xenos action power4. (0/1/7/0 ⇒ 4/1/3/0)",
"itars up nav (4 ⇒ 5). lostPlanet 1A0.",
"ambas charge 2pw (0/2/4/0 ⇒ 0/0/6/0)",
"xenos charge 1pw (4/1/3/0 ⇒ 3/2/3/0)",
"hadsch-hallas action power5. (0/0/4/0 ⇒ 4/0/0/0)",
"ambas action power6. build m 4A4. (0/0/6/0 ⇒ 3/0/3/0)",
"xenos charge 1pw (3/2/3/0 ⇒ 2/3/3/0)",
"xenos build m 2A7.",
"itars charge 1pw (6/1/2/0 ⇒ 5/2/2/0)",
"ambas charge 1pw (3/0/3/0 ⇒ 2/1/3/0)",
"itars build ac1 4A1. tech terra. up terra (0 ⇒ 1).",
"xenos charge 1pw (2/3/3/0 ⇒ 1/4/3/0)",
"hadsch-hallas spend 8c for 2q. action qic2. fedtile fed5.",
"ambas move tradeShip 6B4 10A1 trade 10B1. (2/1/3/0 ⇒ 3/1/2/0)",
"xenos up terra (2 ⇒ 3). (1/4/3/0 ⇒ 0/3/5/0)",
"itars move tradeShip 7A11 5B3 trade 5A6. (5/2/2/0 ⇒ 7/2/0/0)",
"hadsch-hallas spend 8c for 2q. action qic3.",
"ambas move tradeShip 7B5 3A2 trade 5A6. (3/1/2/0 ⇒ 4/1/1/0)",
"xenos action power3. (0/3/5/0 ⇒ 4/3/1/0)",
"itars up gaia (3 ⇒ 4).",
"hadsch-hallas up terra (1 ⇒ 2).",
"ambas special 4pw. (4/1/1/0 ⇒ 0/5/1/0)",
"xenos federation 5A10,5A6,5A7,5B4,5B5,9A2 fed3 using area1: 2.",
"itars build gf 7A6 using area1: 3. (7/2/0/0 ⇒ 4/2/0/3)",
"hadsch-hallas up terra (2 ⇒ 3). (4/0/0/0 ⇒ 1/3/0/0)",
"ambas up terra (0 ⇒ 1).",
"xenos build ts 2A7.",
"itars charge 1pw (4/2/0/3 ⇒ 3/3/0/3)",
"ambas charge 1pw (0/5/1/0 ⇒ 0/4/2/0)",
"itars build m 3A0.",
"xenos charge 1pw (4/3/1/0 ⇒ 3/4/1/0)",
"hadsch-hallas spend 4c for 1q. build m 6B3.",
"itars charge 4pw (3/3/0/3 ⇒ 0/5/1/3)",
"ambas charge 3pw (0/4/2/0 ⇒ 0/1/5/0)",
"xenos charge 1pw (3/4/1/0 ⇒ 2/5/1/0)",
"ambas action power2. build m 2A3. (0/1/5/0 ⇒ 5/1/0/0)",
"itars charge 1pw (0/5/1/3 ⇒ 0/4/2/3)",
"xenos build m 4B2.",
"itars charge 4pw (0/4/2/3 ⇒ 0/0/6/3)",
"ambas charge 1pw (5/1/0/0 ⇒ 4/2/0/0)",
"itars action power7. (0/0/6/3 ⇒ 5/0/3/3)",
"hadsch-hallas move tradeShip 10A1 6B4 trade 6A9. spend 1pw for 1c. (1/3/0/0 ⇒ 1/2/1/0)",
"ambas build ts 4A4.",
"xenos charge 1pw (2/5/1/0 ⇒ 1/6/1/0)",
"xenos special 4pw. (1/6/1/0 ⇒ 0/4/4/0)",
"itars build gf 2A9 using area1: 3. (5/0/3/3 ⇒ 2/0/3/6)",
"hadsch-hallas build ts 6B3.",
"itars charge 4pw (2/0/3/6 ⇒ 0/0/5/6)",
"ambas decline 3pw",
"xenos charge 1pw (0/4/4/0 ⇒ 0/3/5/0)",
"ambas special step. build m 2A4.",
"xenos spend 2pw for 2c. build lab 2A7. tech terra. up terra (3 ⇒ 4). (0/3/5/0 ⇒ 2/3/3/0)",
"ambas charge 1pw (4/2/0/0 ⇒ 3/3/0/0)",
"itars spend 3pw for 1o. build m 6A5. (0/0/5/6 ⇒ 3/0/2/6)",
"ambas decline 3pw",
"hadsch-hallas charge 2pw (1/2/1/0 ⇒ 0/2/2/0)",
"hadsch-hallas move tradeShip 1B0 1A10 trade 1B5.",
"ambas up nav (3 ⇒ 4).",
"xenos up terra (4 ⇒ 5).",
"itars special 4pw. (3/0/2/6 ⇒ 0/2/3/6)",
"hadsch-hallas spend 4c for 1q. build m 4B0. spend 1pw for 1c. (0/2/2/0 ⇒ 1/2/1/0)",
"itars charge 2pw (0/2/3/6 ⇒ 0/0/5/6)",
"xenos charge 1pw (2/3/3/0 ⇒ 1/4/3/0)",
"ambas federation 2A3,2A4,2A5,2B0,2B1,2B3,6A0,6A1,6B1 fed2 using area1: 3, area2: 1. (3/3/0/0 ⇒ 0/2/0/0)",
"xenos spend 3pw for 3c. build ts 8B2. (1/4/3/0 ⇒ 4/4/0/0)",
"hadsch-hallas charge 3pw (1/2/1/0 ⇒ 0/1/3/0)",
"ambas charge 1pw (0/2/0/0 ⇒ 0/1/1/0)",
"itars spend 3pw for 1o. build gf 1A3 using area1: 3. (0/0/5/6 ⇒ 0/0/2/9)",
"hadsch-hallas spend 1pw for 1c. move tradeShip 7A10 3A1 trade 5A7. (0/1/3/0 ⇒ 1/1/2/0)",
"ambas build ts 7B2.",
"hadsch-hallas charge 3pw (1/1/2/0 ⇒ 0/0/4/0)",
"xenos burn 2. spend 2pw for 2c. build m 8B0. (4/4/0/0 ⇒ 6/0/0/0)",
"itars build ts 9A8.",
"ambas charge 1pw (0/1/1/0 ⇒ 0/0/2/0)",
"hadsch-hallas build lab 6B3. tech terra. up terra (3 ⇒ 4). spend 2pw for 2c. (0/0/4/0 ⇒ 2/0/2/0)",
"xenos charge 1pw (6/0/0/0 ⇒ 5/1/0/0)",
"ambas spend 1pw for 1c. spend 1pw for 1c. build lab 4A4. tech terra. up terra (1 ⇒ 2). (0/0/2/0 ⇒ 2/0/0/0)",
"xenos charge 1pw (5/1/0/0 ⇒ 4/2/0/0)",
"hadsch-hallas charge 1pw (2/0/2/0 ⇒ 1/1/2/0)",
"xenos pass booster10 returning booster6",
"itars pass booster6 returning booster2",
"hadsch-hallas spend 9c for 3o. build ac2 6B3. tech free3. up eco (3 ⇒ 4). spend 1pw for 1c. (1/1/2/0 ⇒ 2/1/1/0)",
"ambas decline 3pw",
"xenos charge 1pw (4/2/0/0 ⇒ 3/3/0/0)",
"ambas up eco (1 ⇒ 2).",
"hadsch-hallas special q.",
"ambas up eco (2 ⇒ 3). (2/0/0/0 ⇒ 0/1/1/0)",
"hadsch-hallas up int (0 ⇒ 1).",
"ambas special swap-PI (from 6B1). swap-PI 1B5 (from 6B1).",
"hadsch-hallas spend 1q for 1o. spend 3c for 1o. build m 3A7.",
"xenos charge 1pw (3/3/0/0 ⇒ 2/4/0/0)",
"ambas spend 1pw for 1c. spend 1k for 1c. build m 4B4. (0/1/1/0 ⇒ 1/1/0/0)",
"xenos charge 1pw (2/4/0/0 ⇒ 1/5/0/0)",
"hadsch-hallas charge 1pw (2/1/1/0 ⇒ 1/2/1/0)",
"hadsch-hallas spend 1pw for 1c. pass booster2 returning booster8 (1/2/1/0 ⇒ 2/2/0/0)",
"ambas pass booster8 returning booster4",
"itars income 1t. income 1t (0/0/2/9 ⇒ 0/0/4/9)",
"hadsch-hallas income 1t. income 2t (2/2/0/0 ⇒ 0/0/7/0)",
"ambas income 2t (1/1/0/0 ⇒ 0/0/4/0)",
"itars decline tech (0/0/4/9 ⇒ 9/0/4/0)",
"xenos burn 1. action power4. (0/3/3/0 ⇒ 4/1/0/0)",
"itars build m 1A3.",
"hadsch-hallas spend 8c for 2q. spend 2pw for 2c. action qic3. (0/0/7/0 ⇒ 2/0/5/0)",
"ambas action power5. (0/0/4/0 ⇒ 4/0/0/0)",
"xenos build ts 3A6.",
"hadsch-hallas charge 1pw (2/0/5/0 ⇒ 1/1/5/0)",
"itars decline 4pw",
"ambas decline 3pw",
"itars build m 2A9.",
"ambas charge 1pw (4/0/0/0 ⇒ 3/1/0/0)",
"xenos charge 2pw (4/1/0/0 ⇒ 2/3/0/0)",
"hadsch-hallas spend 12c for 3q. action qic2. fedtile fed5.",
"ambas up eco (3 ⇒ 4).",
"xenos build m 9B5.",
"itars charge 2pw (9/0/4/0 ⇒ 7/2/4/0)",
"ambas charge 1pw (3/1/0/0 ⇒ 2/2/0/0)",
"itars federation 3A0,3A11,3A8,3A9,3B5,4A1,6A4,6A5 fed4 using area1: 4. (7/2/4/0 ⇒ 3/2/4/0)",
"hadsch-hallas build lab 8B4. tech adv-dip. cover free2. up int (1 ⇒ 2).",
"xenos charge 2pw (2/3/0/0 ⇒ 0/5/0/0)",
"ambas build lab 7B2. tech adv-eco. cover terra. up eco (4 ⇒ 5). spend 1pw for 1c. (2/2/0/0 ⇒ 1/0/3/0)",
"hadsch-hallas decline 3pw",
"itars charge 1pw (3/2/4/0 ⇒ 2/3/4/0)",
"xenos spend 1q for 1o. build ac2 2A7. tech free3. up int (1 ⇒ 2).",
"itars charge 1pw (2/3/4/0 ⇒ 1/4/4/0)",
"ambas charge 1pw (1/0/3/0 ⇒ 0/1/3/0)",
"itars build ts 9A7.",
"ambas charge 1pw (0/1/3/0 ⇒ 0/0/4/0)",
"xenos charge 1pw (0/5/0/0 ⇒ 0/4/1/0)",
"hadsch-hallas build m 4A8. spend 1pw for 1c. (1/1/5/0 ⇒ 2/1/4/0)",
];
const engine = new Engine(moves, { frontiers: true, advancedRules: true });
expect(() => engine.move("ambas move tradeShip 10A1 6A7 trade 6B3.")).to.not.throw();
});
});

@@ -24,3 +24,3 @@ import Engine from "../engine";

export type TradeOption = {
building: Building;
buildings: Building[];
domestic?: boolean;

@@ -36,3 +36,3 @@ free?: boolean;

{
building: Building.Mine,
buildings: [Building.Mine],
domestic: true,

@@ -44,3 +44,3 @@ free: true,

{
building: Building.Mine,
buildings: [Building.Mine],
base: [],

@@ -51,3 +51,3 @@ bonus: Reward.parse("1c,1o"),

{
building: Building.TradingStation,
buildings: [Building.TradingStation],
base: Reward.parse("5c"),

@@ -57,3 +57,3 @@ bonus: Reward.parse("3c,1pw"),

{
building: Building.ResearchLab,
buildings: [Building.ResearchLab],
base: Reward.parse("2k"),

@@ -63,3 +63,3 @@ bonus: Reward.parse("1k"),

{
building: Building.Academy1,
buildings: [Building.Academy1, Building.Academy2],
base: Reward.parse("2k"),

@@ -70,3 +70,3 @@ bonus: Reward.parse("1k"),

{
building: Building.PlanetaryInstitute,
buildings: [Building.PlanetaryInstitute],
base: Reward.parse("1t,2pw"),

@@ -76,3 +76,3 @@ bonus: Reward.parse("4pw"),

{
building: Building.Colony,
buildings: [Building.Colony],
base: Reward.parse("3vp"),

@@ -219,3 +219,3 @@ bonus: Reward.parse("2vp"),

const domestic = h.data.player === player;
const option = tradeOptions.find((o) => o.building === building && !!o.domestic === domestic);
const option = tradeOptions.find((o) => o.buildings.includes(building) && !!o.domestic === domestic);
if (option) {

@@ -222,0 +222,0 @@ const cost = tradeCost(guest, option);

@@ -82,4 +82,4 @@ import {

export type PossibleBid = { faction: Faction; bid: number[] };
type TechTileWithPos = { tile: TechTile; pos: TechTilePos };
type AdvTechTileWithPos = { tile: AdvTechTile; pos: AdvTechTilePos };
export type TechTileWithPos = { tile: TechTile; pos: TechTilePos };
export type AdvTechTileWithPos = { tile: AdvTechTile; pos: AdvTechTilePos };
export type ChooseTechTile = TechTileWithPos | AdvTechTileWithPos;

@@ -86,0 +86,0 @@ export type AvailableBuildCommandData = { buildings: AvailableBuilding[] };

@@ -21,3 +21,2 @@ import assert from "assert";

Round,
RoundScoring,
ScoringTile,

@@ -55,3 +54,3 @@ SubPhase,

import { lastTile } from "./research-tracks";
import { roundScorings } from "./tiles/scoring";
import { roundScoringEvents } from "./tiles/scoring";
import { isVersionOrLater } from "./utils";

@@ -919,6 +918,5 @@

get currentRoundScoringEvents() {
const roundScoringTile = this.tiles.scorings.round[this.round - 1];
const roundScoring = roundScorings[roundScoringTile];
return roundScoring && Event.parse(roundScoring, `round${this.round}` as RoundScoring);
get currentRoundScoringEvents(): Event[] | null {
const tile = this.tiles.scorings.round[this.round - 1];
return tile && roundScoringEvents(tile, this.round);
}

@@ -925,0 +923,0 @@

import { expect } from "chai";
import Engine from "../engine";
import { Building, Command, Operator, Planet, Player } from "../enums";
import { Building, Command, Operator, Planet, Player, Resource } from "../enums";

@@ -136,8 +136,5 @@ const parseMoves = Engine.parseMoves;

const engine = new Engine(moves);
const income = engine.player(Player.Player1).income;
// tslint:disable-next-line no-unused-expression
expect(income.includes("4pw")).to.be.true;
// tslint:disable-next-line no-unused-expression
expect(income.includes("t")).to.be.false;
const player = engine.player(Player.Player1);
expect(player.resourceIncome(Resource.ChargePower)).to.equal(4);
expect(player.resourceIncome(Resource.GainToken)).to.equal(0);
});

@@ -144,0 +141,0 @@

@@ -83,4 +83,8 @@ import assert from "assert";

get federations(): Player[] {
return this.data.federations ?? [];
}
belongsToFederationOf(player: Player): boolean {
return this.data.federations && this.data.federations.includes(player);
return this.federations.includes(player);
}

@@ -87,0 +91,0 @@

@@ -5,4 +5,3 @@ import assert from "assert";

import { BoardAction, Command, Federation, Player as PlayerEnum } from "../enums";
import Reward from "../reward";
import federations from "../tiles/federations";
import { federationRewards } from "../tiles/federations";

@@ -20,3 +19,3 @@ export function moveChooseFederationTile(

if (rescore) {
engine.player(player).gainRewards(Reward.parse(federations[federation]), BoardAction.Qic2);
engine.player(player).gainRewards(federationRewards(federation), BoardAction.Qic2);
} else {

@@ -23,0 +22,0 @@ engine.player(player).gainFederationToken(federation);

@@ -39,3 +39,3 @@ import assert from "assert";

engine.player(player).gainTechTile(tileAvailable.tile, tileAvailable.pos);
engine.player(player).gainTechTile(tileAvailable);
engine.tiles.techs[pos].count -= 1;

@@ -42,0 +42,0 @@

import { EventEmitter } from "eventemitter3";
import { cloneDeep, fromPairs } from "lodash";
import { TRADE_COST } from "./available/ships";
import { BrainstoneActionData, BrainstoneWarning } from "./available/types";
import {
AdvTechTile,
AdvTechTilePos,
Booster,
Building,
Command,
Expansion,
Federation,
PowerArea,
ResearchField,
Resource,
Ship,
TechTile,
TechTilePos,
} from "./enums";
import { BrainstoneActionData, BrainstoneWarning, ChooseTechTile } from "./available/types";
import { Booster, Building, Command, Expansion, Federation, PowerArea, ResearchField, Resource, Ship } from "./enums";
import { EventSource } from "./events";

@@ -104,3 +90,3 @@ import { FactionBoard } from "./faction-boards";

booster: Booster;
techs: Array<{ tile: TechTile | AdvTechTile; pos: TechTilePos | AdvTechTilePos; enabled: boolean }>;
techs: Array<ChooseTechTile & { enabled: boolean }>;
federations: Array<{ tile: Federation; green: boolean }>;

@@ -107,0 +93,0 @@ } = {

@@ -79,3 +79,3 @@ import { expect } from "chai";

expect(orderedEvents).to.be.equal("1c,1o,1k,1t");
expect(orderedEvents).to.be.equal("c,o,k,t");
});

@@ -82,0 +82,0 @@ });

@@ -6,7 +6,6 @@ import assert from "assert";

import spanningTree from "./algorithms/spanning-tree";
import { ChooseTechTile } from "./available/types";
import { stdBuildingValue } from "./buildings";
import { terraformingCost } from "./cost";
import {
AdvTechTile,
AdvTechTilePos,
Booster,

@@ -30,3 +29,2 @@ Building,

Ship,
TechPos,
TechTile,

@@ -53,6 +51,6 @@ TechTilePos,

import Reward from "./reward";
import boosts from "./tiles/boosters";
import federationTiles, { isGreen } from "./tiles/federations";
import { boosterEvents } from "./tiles/boosters";
import { federationRewards, isGreen } from "./tiles/federations";
import { finalScorings } from "./tiles/scoring";
import techs, { isAdvanced } from "./tiles/techs";
import { isAdvanced, techTileEvents } from "./tiles/techs";
import { isVersionOrLater } from "./utils";

@@ -136,17 +134,11 @@

get income() {
return Reward.toString(
Reward.merge([].concat(...this.events[Operator.Income].map((event) => event.rewards))),
true
);
return Reward.toString(this.incomeRewards, true);
}
resourceIncome(resource: ResourceEnum) {
const i = this.income;
const index = i.search(new RegExp("[0-9]+" + resource));
get incomeRewards() {
return Reward.merge([].concat(...this.events[Operator.Income].map((event) => event.rewards)));
}
if (index < 0) {
return 0;
}
return parseInt(i.substr(index));
resourceIncome(resource: ResourceEnum): number {
return this.incomeRewards.find((r) => r.type === resource)?.count ?? 0;
}

@@ -465,7 +457,3 @@

if (event.operator === Operator.Once) {
const times = this.eventConditionCount(event.condition);
this.gainRewards(
event.rewards.map((reward) => new Reward(reward.count * times, reward.type)),
event.source
);
this.gainRewards(this.eventConditionRewards(event), event.source);
}

@@ -498,8 +486,7 @@ }

removeRoundBoosterEvents(type?: Operator.Income) {
let eventList = Event.parse(boosts[this.data.tiles.booster], this.data.tiles.booster);
eventList = eventList.filter(
const events = boosterEvents(this.data.tiles.booster).filter(
(ev) => (type && ev.operator === Operator.Income) || (!type && ev.operator !== Operator.Income)
);
for (const event of eventList) {
for (const event of events) {
this.removeEvent(event);

@@ -688,15 +675,15 @@ }

this.data.tiles.booster = roundBooster;
this.loadEvents(Event.parse(boosts[roundBooster], roundBooster));
this.loadEvents(boosterEvents(roundBooster));
}
gainTechTile(tile: TechTile | AdvTechTile, pos: TechTilePos | AdvTechTilePos) {
const advanced = isAdvanced(pos);
gainTechTile(chooseTechTile: ChooseTechTile) {
const advanced = isAdvanced(chooseTechTile.pos);
if (advanced) {
this.data.removeGreenFederation();
}
this.data.tiles.techs.push({ tile, pos, enabled: true });
this.loadEvents(Event.parse(techs[tile], !advanced ? (`tech-${pos}` as TechPos) : (pos as AdvTechTilePos)));
this.data.tiles.techs.push({ ...chooseTechTile, enabled: true });
this.loadEvents(techTileEvents(chooseTechTile));
// resets federationCache if Special PA->4pw
if (tile === TechTile.Tech3) {
if (chooseTechTile.tile === TechTile.Tech3) {
this.federationCache = null;

@@ -710,3 +697,3 @@ }

const events = Event.parse(techs[tile.tile], `tech-${pos}` as TechPos);
const events = techTileEvents(tile);
this.removeEvents(events);

@@ -774,9 +761,12 @@

// this is for pass tile income (e.g. round boosters, adv tiles)
return this.events[Operator.Pass].map((event) => {
const times = this.eventConditionCount(event.condition);
const rewards = event.rewards.map((reward) => new Reward(reward.count * times, reward.type));
return new Event(rewards.join(","), event.source);
});
return this.events[Operator.Pass].map(
(event) => new Event(this.eventConditionRewards(event).join(","), event.source)
);
}
eventConditionRewards(event: Event): Reward[] {
const times = this.eventConditionCount(event.condition);
return event.rewards.map((reward) => new Reward(reward.count * times, reward.type));
}
receivePassIncome() {

@@ -900,3 +890,3 @@ for (const e of this.passIncomeEvents()) {

this.gainRewards(Reward.parse(federationTiles[federation]), Command.FormFederation);
this.gainRewards(federationRewards(federation), Command.FormFederation);
this.receiveTriggerIncome(Condition.Federation);

@@ -903,0 +893,0 @@ }

@@ -45,4 +45,4 @@ import { expect } from "chai";

expect(new Reward("3vp").toString()).to.equal("3vp");
expect(new Reward("1vp").toString()).to.equal("1vp");
expect(new Reward("vp").toString()).to.equal("1vp");
expect(new Reward("1vp").toString()).to.equal("vp");
expect(new Reward("vp").toString()).to.equal("vp");
expect(new Reward("5c").toString()).to.equal("5c");

@@ -52,3 +52,3 @@ });

it("should convert an array of rewards to a string", () => {
expect(Reward.toString([new Reward("3vp"), new Reward("q")], true)).to.equal("1q,3vp");
expect(Reward.toString([new Reward("3vp"), new Reward("q")], true)).to.equal("q,3vp");
});

@@ -55,0 +55,0 @@

@@ -45,3 +45,3 @@ import assert from "assert";

toStringWithZero() {
return `${this.count}${this.type}`;
return this.count === 1 ? this.type.toString() : `${this.count}${this.type}`;
}

@@ -88,3 +88,2 @@

static toString(rewards: Reward[], sorted = true) {
// const sortOrder = ['c', 'o', 'k', 'q', 'pw'];
const sortOrder = ["pw", "q", "k", "o", "c"];

@@ -91,0 +90,0 @@ if (sorted) {

import { Booster } from "../enums";
import Event from "../events";
export default {
const boosterSpec: { [key in Booster]: string[] } = {
[Booster.Booster1]: ["+k", "+o"],

@@ -15,1 +16,5 @@ [Booster.Booster2]: ["+o", "+2t"],

};
export function boosterEvents(booster: Booster): Event[] {
return Event.parse(boosterSpec[booster], booster);
}
import { Federation } from "../enums";
import Reward from "../reward";
export default {
const federationSpec: { [key in Federation]: string } = {
[Federation.Fed1]: "12vp",

@@ -13,4 +14,8 @@ [Federation.Fed2]: "8vp,q",

export function federationRewards(federation: Federation): Reward[] {
return Reward.parse(federationSpec[federation]);
}
export function isGreen(federation: Federation) {
return federation !== Federation.Fed1;
}

@@ -1,4 +0,5 @@

import { Condition, FinalTile, ScoringTile } from "../enums";
import { Condition, FinalTile, RoundScoring, ScoringTile } from "../enums";
import Event from "../events";
const roundScorings = {
const roundScorings: { [key in ScoringTile]: string[] } = {
[ScoringTile.Score1]: ["step >> 2vp"],

@@ -16,3 +17,8 @@ [ScoringTile.Score2]: ["a >> 2vp"],

const finalScorings = {
export function roundScoringEvents(tile: ScoringTile, round: number): Event[] {
const roundScoring = roundScorings[tile];
return Event.parse(roundScoring, `round${round}` as RoundScoring);
}
export const finalScorings: { [key in FinalTile]: { condition: Condition; neutralPlayer: number } } = {
[FinalTile.Structure]: { condition: Condition.Structure, neutralPlayer: 11 },

@@ -25,3 +31,1 @@ [FinalTile.StructureFed]: { condition: Condition.StructureFed, neutralPlayer: 10 },

};
export { roundScorings, finalScorings };

@@ -1,4 +0,7 @@

import { AdvTechTile, AdvTechTilePos, Operator, TechTile, TechTilePos } from "../enums";
import { ChooseTechTile } from "../available/types";
import { AdvTechTile, AdvTechTilePos, Operator, TechPos, TechTile, TechTilePos } from "../enums";
import Event, { EventSource } from "../events";
import Reward from "../reward";
export default {
const techTileSpec: { [key in TechTile | AdvTechTile]: string[] } = {
[TechTile.Tech1]: ["o,q"],

@@ -31,4 +34,20 @@ [TechTile.Tech2]: ["pt > k"],

export function techTileEventWithSource(tile: TechTile | AdvTechTile, source: EventSource): Event[] {
return Event.parse(techTileSpec[tile], source);
}
export function techTileEvents(chooseTechTile: ChooseTechTile): Event[] {
const pos = chooseTechTile.pos;
return techTileEventWithSource(
chooseTechTile.tile,
isAdvanced(pos) ? (pos as AdvTechTilePos) : (`tech-${pos}` as TechPos)
);
}
export function techTileRewards(tile: TechTile | AdvTechTile): Reward[] {
return techTileEventWithSource(tile, null).flatMap((e) => e.rewards);
}
export function isAdvanced(pos: TechTilePos | AdvTechTilePos): boolean {
return pos.startsWith("adv");
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc