Skip to content

Commit

Permalink
CEO Huan
Browse files Browse the repository at this point in the history
  • Loading branch information
kberg committed Feb 11, 2025
1 parent 8b8d34a commit 611e257
Show file tree
Hide file tree
Showing 8 changed files with 116 additions and 4 deletions.
1 change: 1 addition & 0 deletions src/client/components/card/CardRenderItemComponent.vue
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,7 @@ export default Vue.extend({
case CardRenderItemType.TR:
case CardRenderItemType.WILD:
case CardRenderItemType.UNDERGROUND_RESOURCES:
case CardRenderItemType.TRADE:
result = '<div class="card-x">x</div>';
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/server/cards/ceos/CeoCardManifest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {Gaia} from './Gaia';
import {Gordon} from './Gordon';
import {Greta} from './Greta';
import {HAL9000} from './HAL9000';
// import {Huan} from './Huan';
import {Huan} from './Huan';
import {Ingrid} from './Ingrid';
import {Jansson} from './Jansson';
import {Karen} from './Karen';
Expand Down Expand Up @@ -58,7 +58,7 @@ export const CEO_CARD_MANIFEST = new ModuleManifest({
[CardName.GORDON]: {Factory: Gordon},
[CardName.GRETA]: {Factory: Greta},
[CardName.HAL9000]: {Factory: HAL9000},
// [CardName.HUAN]: {Factory: Huan, compatibility: 'colonies'},
[CardName.HUAN]: {Factory: Huan, compatibility: 'colonies'},
[CardName.INGRID]: {Factory: Ingrid},
[CardName.JANSSON]: {Factory: Jansson},
[CardName.KAREN]: {Factory: Karen, compatibility: 'prelude'},
Expand Down
38 changes: 38 additions & 0 deletions src/server/cards/ceos/Huan.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import {CardName} from '../../../common/cards/CardName';
import {CardRenderer} from '../render/CardRenderer';
import {PlayerInput} from '../../PlayerInput';
import {Player} from '../../Player';
import {CeoCard} from './CeoCard';
import {all, cancelled} from '../Options';

export class Huan extends CeoCard {
constructor() {
super({
name: CardName.HUAN,
metadata: {
cardNumber: 'L29',
renderData: CardRenderer.builder((b) => {
b.opgArrow().text('ACTIVATE THE BELOW ABILITY');
b.br.br;
b.trade({all, cancelled}).asterix().tradeFleet();
b.br.br;
}),
description: 'ALL OPPONENTS CANNOT TRADE NEXT GENERATION. Gain 1 Trade Fleet.',
},
});
}

public action(player: Player): PlayerInput | undefined {
const game = player.game;
player.colonies.increaseFleetSize();
game.syndicatePirateRaider = player.id;

game.log(
'All players except ${0} may not trade next generation.',
(b) => b.player(player),
);

this.isDisabled = true;
return undefined;
}
}
4 changes: 2 additions & 2 deletions src/server/cards/render/CardRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,8 +168,8 @@ abstract class Builder<T> {
public trade(options?: ItemOptions): this {
return this._appendToRow(new CardRenderItem(CardRenderItemType.TRADE, -1, options));
}
public tradeFleet(): this {
return this._appendToRow(new CardRenderItem(CardRenderItemType.TRADE_FLEET));
public tradeFleet(options?: ItemOptions): this {
return this._appendToRow(new CardRenderItem(CardRenderItemType.TRADE_FLEET, -1, options));
}

public colonies(amount: number = 1, options?: ItemOptions): this {
Expand Down
5 changes: 5 additions & 0 deletions src/server/colonies/Colony.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ export abstract class Colony implements IColony {
if (game.syndicatePirateRaider) {
if (game.syndicatePirateRaider === this.visitor) {
this.visitor = undefined;
} else {
const raider = game.getPlayerById(game.syndicatePirateRaider);
if (raider.cardIsInEffect(CardName.HUAN)) {
this.visitor = undefined;
}
}
} else {
this.visitor = undefined;
Expand Down
8 changes: 8 additions & 0 deletions src/server/player/Colonies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,14 @@ export class Colonies {
if (syndicatePirateRaider === undefined) {
this.tradesThisGeneration = 0;
} else if (syndicatePirateRaider === this.player.id) {
// CEO effect: Disable all other players from trading next gen,
// but free up all colonies (don't leave their trade fleets stuck there)
if (this.player.cardIsInEffect(CardName.HUAN)) {
for (const player of this.player.getOpponents()) {
// Magic number high enough to disable other players' trading
player.colonies.tradesThisGeneration = 50;
}
}
this.tradesThisGeneration = 0;
}
}
Expand Down
8 changes: 8 additions & 0 deletions src/styles/cards_v2.less
Original file line number Diff line number Diff line change
Expand Up @@ -1595,6 +1595,14 @@
height: 40px;
width: 48px;
background-size: 48px;
.card-x {
position: absolute;
color: red;
font-size: 44px;
left: 12px;
top: 13px;
filter: drop-shadow(1px 0px 1px #888) drop-shadow(-1px 0px 1px #888) drop-shadow(0px 1px 1px #888) drop-shadow(0px -1px 1px #888)
}
}
.card-resource-trade--S {
height: 30px !important;
Expand Down
52 changes: 52 additions & 0 deletions tests/cards/ceo/Huan.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import {expect} from 'chai';
import {Huan} from '../../../src/server/cards/ceos/Huan';
import {IGame} from '../../../src/server/IGame';
import {Player} from '../../../src/server/Player';
import {testGame} from '../../TestGame';
import {forceGenerationEnd, runAllActions} from '../../TestingUtils';

describe('Huan', () => {
let card: Huan;
let game: IGame;
let player: Player;
let player2: Player;

beforeEach(() => {
card = new Huan();

[game, player, player2] = testGame(2, {coloniesExtension: true});
player.playedCards.push(card);
});

it('Takes action', () => {
game.colonies[0].trade(player);
game.colonies[1].trade(player2);

expect(player.colonies.tradesThisGeneration).eq(1);
expect(player2.colonies.tradesThisGeneration).eq(1);
expect(game.colonies[0].visitor).eq(player.id);
expect(game.colonies[1].visitor).eq(player2.id);

// Blocks opponents from trading, but clears all colony visitors
const initialFleetSize = player.colonies.getFleetSize();
card.action(player);
forceGenerationEnd(game);

expect(player.colonies.tradesThisGeneration).eq(0);
expect(player2.colonies.tradesThisGeneration).eq(50);
expect(game.colonies[0].visitor).is.undefined;
expect(game.colonies[1].visitor).is.undefined;

// Player gains an extra trade fleet
expect(player.colonies.getFleetSize()).to.eq(initialFleetSize + 1);
});

it('Can only act once per game', () => {
card.action(player);
runAllActions(game);

forceGenerationEnd(game);
expect(card.isDisabled).is.true;
expect(card.canAct(player)).is.false;
});
});

0 comments on commit 611e257

Please sign in to comment.