CardFactory Cleaning
Post MTG Forge Related Programming Questions Here
Moderators: timmermac, Blacksmith, KrazyTheFox, Agetian, friarsol, CCGHQ Admins
CardFactory Cleaning
by zerker2000 » 22 Jun 2009, 11:38
Ok, this shall be where I'll post card coding/cleanup suggestions. They will be in the format of "<cards.txt text> /n/n <suggested Factory code>", and I have three so far:
---1 Blight Sickle: At Rob's request, I shall paste a copy here:
---1 Blight Sickle: At Rob's request, I shall paste a copy here:
- Code: Select all
Blight Sickle
2
Artifact Equipment
Equipped creature gets +1/+0 and has Wither.
- Code: Select all
//*************** START *********** START **************************
if (cardName.equals("Blight Sickle"))
{
final Ability equip = new Ability(card, "2")
{
public void resolve()
{
if (AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) )
{
if (card.isEquipping())
{
Card crd = card.getEquipping().get(0);
if (crd.equals(getTargetCard()) )
return;
card.unEquipCard(crd);
}
card.equipCard(getTargetCard());
}
}
public boolean canPlay()
{
return AllZone.getZone(card).is(Constant.Zone.Play) &&
AllZone.Phase.getActivePlayer().equals(card.getController()) &&
!AllZone.Phase.getPhase().equals("End of Turn") &&
!AllZone.Phase.getPhase().equals(Constant.Phase.Combat_Declare_Blockers_InstantAbility);
}
public boolean canPlayAI()
{
return getCreature().size() != 0 && !card.isEquipping();
}
public void chooseTargetAI()
{
Card target = CardFactoryUtil.AI_getBestCreature(getCreature());
setTargetCard(target);
}
CardList getCreature()
{
CardList list = new CardList(AllZone.Computer_Play.getCards());
list = list.filter(new CardListFilter()
{
public boolean addCard(Card c)
{
return c.isCreature() && (!CardFactoryUtil.AI_doesCreatureAttack(c)) && CardFactoryUtil.canTarget(card, c) &&
(! c.getKeyword().contains("Defender"));
}
});
// list.remove(card); // if mana-only cost, allow self-target
return list;
}//getCreature()
};//equip ability
Command onEquip = new Command()
{
private static final long serialVersionUID = 8130682765214560887L;
public void execute()
{
if (card.isEquipping())
{
Card crd = card.getEquipping().get(0);
crd.addExtrinsicKeyword("Wither");
crd.addSemiPermanentAttackBoost(1);
}
}//execute()
};//Command
Command onUnEquip = new Command()
{
private static final long serialVersionUID = 5783423127748320501L;
public void execute()
{
if (card.isEquipping())
{
Card crd = card.getEquipping().get(0);
crd.removeExtrinsicKeyword("Wither");
crd.addSemiPermanentAttackBoost(-1);
}
}//execute()
};//Command
Input runtime = new Input()
{
private static final long serialVersionUID = -6785656229070523470L;
public void showMessage()
{
//get all creatures you control
CardList list = new CardList();
list.addAll(AllZone.Human_Play.getCards());
list = list.getType("Creature");
stopSetNext(CardFactoryUtil.input_targetSpecific(equip, list, "Select target creature to equip", true));
}
};//Input
equip.setBeforePayMana(runtime);
equip.setDescription("Equip: 2");
card.addSpellAbility(equip);
card.setEquip(onEquip);
card.setUnEquip(onUnEquip);
} //*************** END ************ END **************************
- Code: Select all
Akki Drillmaster
2 R
Creature Goblin Shaman
no text
2/2
>TgtKPump T:Haste
- Code: Select all
- Code: Select all
//***Keep as is:
Sensei's Divining Top
1
Artifact
no text
- Code: Select all
else if(cardName.equals("Sensei's Divining Top"))
{
//ability2: Draw card, and put divining top on top of library
final SpellAbility ability2 = new Ability_Tap(card, "0")
{
private static final long serialVersionUID = -2523015092351744208L;
public void resolve()
{
String player = card.getController();
String owner = card.getOwner();
PlayerZone play = AllZone.getZone(Constant.Zone.Play, player);
PlayerZone lib = AllZone.getZone(Constant.Zone.Library, owner);
AllZone.GameAction.drawCard(player);
play.remove(card);
lib.add(card,0); //move divining top to top of library
card.untap();
}
public boolean canPlayAI()
{
return false;
}
public boolean canPlay()
{
if (AllZone.getZone(card).is(Constant.Zone.Play))
return true;
else
return false;
}//canPlay()
};//SpellAbility ability2
ability2.setBeforePayMana(new Input()
{
private static final long serialVersionUID = -4773496833654414458L;
@SuppressWarnings("unused") // check
int check = -1;
public void showMessage()
{
AllZone.Stack.push(ability2);
stop();
}//showMessage()
});
//ability (rearrange top 3 cards) :
final SpellAbility ability1 = new Ability(card, "1")
{
public void resolve()
{
String player = card.getController();
PlayerZone lib = AllZone.getZone(Constant.Zone.Library, player);
if (lib.size() < 3)
return;
CardList topThree = new CardList();
//show top 3 cards:
topThree.add(lib.get(0));
topThree.add(lib.get(1));
topThree.add(lib.get(2));
> for (int i=1;i<=3;i++){
> String Title = "Put on top: ";
> if (i==2) Title = "Put second from top: ";
> if (i==3) Title = "Put third from top: ";
> Object o = AllZone.Display.getChoiceOptional(Title, topThree.toArray());
> if(o == null) break;
> Card c_1 = (Card)o;
> topThree.remove(c_1);
> lib.remove(c_1);
> lib.add(c_1,i-1);
> }
}
public boolean canPlayAI()
{
return false;
}
public boolean canPlay()
{
if (AllZone.getZone(card).is(Constant.Zone.Play))
return true;
else
return false;
}//canPlay()
};//SpellAbility ability1
ability1.setDescription("1: Look at the top three cards of your library, then put them back in any order.");
ability1.setStackDescription("Sensei's Divining Top - rearrange top 3 cards");
card.addSpellAbility(ability1);
ability1.setBeforePayMana(new Input_PayManaCost(ability1));
ability2.setDescription("tap: Draw a card, then put Sensei's Divining Top on top of its owner's library.");
ability2.setStackDescription("Sensei's Divining Top - draw a card, then put back on owner's library");
ability2.setBeforePayMana(new Input_NoCost_TapAbility((Ability_Tap) ability2));
card.addSpellAbility(ability2);
}
O forest, hold thy wand'ring son
Though fears assail the door.
O foliage, cloak thy ravaged one
In vestments cut for war.
--Eladamri, the Seed of Freyalise
Though fears assail the door.
O foliage, cloak thy ravaged one
In vestments cut for war.
--Eladamri, the Seed of Freyalise
- zerker2000
- Programmer
- Posts: 569
- Joined: 09 May 2009, 21:40
- Location: South Pasadena, CA
- Has thanked: 0 time
- Been thanked: 0 time
Re: CardFactory Cleaning
by DennisBergkamp » 22 Jun 2009, 17:16
Cool, I'll make these changes! You seem to be picking up things pretty quickly, Zerker
Yes, I'm sure a lot of the cards' code can be compacted, or abilities turned into keywords (Rob's been doing a lot of those).
Anyway, if you're looking for redundant code, look at some of the Planeswalkers, I think there's a lot of bloated code there.
Yes, I'm sure a lot of the cards' code can be compacted, or abilities turned into keywords (Rob's been doing a lot of those).
Anyway, if you're looking for redundant code, look at some of the Planeswalkers, I think there's a lot of bloated code there.
-
DennisBergkamp - AI Programmer
- Posts: 2602
- Joined: 09 Sep 2008, 15:46
- Has thanked: 0 time
- Been thanked: 0 time
Bombs Away!
by zerker2000 » 23 Jun 2009, 09:42
Ok, part two.
Make sure to paste the following into somewhere you can see what I'm actually doing(and hopefully catch any mistakes I made, though the basic stuff was caught by eclipse):
--Cards.txt--
Make sure to paste the following into somewhere you can see what I'm actually doing(and hopefully catch any mistakes I made, though the basic stuff was caught by eclipse):
--Cards.txt--
- Code: Select all
AEther Spellbomb
1
Artifact
no text
1, Sacrifice AEther Spellbomb: Draw a card.
Lifespark Spellbomb
1
Artifact
no text
1, Sacrifice Lifespark Spellbomb: Draw a card.
Pyrite Spellbomb
1
Artifact
no text
1, Sacrifice Pyrite Spellbomb: Draw a card.
Necrogen Spellbomb
1
Artifact
no text
1, Sacrifice Necrogen Spellbomb: Draw a card.
Sunbeam Spellbomb
1
Artifact
no text
1, Sacrifice Sunbeam Spellbomb: Draw a card.
- Code: Select all
public static SpellAbility ability_Spellbomb(final Card sourceCard){
final SpellAbility ability = new Ability(sourceCard, "1")
{
public boolean canPlay()
{
return AllZone.GameAction.isCardInPlay(sourceCard)&&!AllZone.Stack.getSourceCards().contains(sourceCard);//in play and not already activated(Sac cost problems)
}
public boolean canPlayAI() {return (AllZone.Computer_Hand.size() < 4)&&(AllZone.Computer_Library.size()>0)&&MyRandom.random.nextBoolean();}
public void resolve()
{
AllZone.GameAction.drawCard(sourceCard.getController());
AllZone.GameAction.sacrifice(getSourceCard());
}
};
ability.setDescription("1, Sacrifice "+sourceCard.getName()+": Draw a card.");
ability.setStackDescription(sourceCard.getName() +" - Draw a card.");
return ability;
- Code: Select all
if(cardName.equals("AEther Spellbomb"))
{
final Ability ability = new Ability(card, "U")
{
public boolean canPlay()
{
return AllZone.GameAction.isCardInPlay(card)&&!AllZone.Stack.getSourceCards().contains(card);
}
public boolean canPlayAI()
{
setTargetCard(CardFactoryUtil.AI_getBestCreature(new CardList(AllZone.Human_Play.getCards())));
return ((AllZone.Computer_Hand.size() > 2)&&(getTargetCard() != null)) ;
}
public void resolve()
{
final Card[] target = new Card[1];
target[0] = getTargetCard();
PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, target[0].getController());
if(AllZone.GameAction.isCardInPlay(target[0]) && CardFactoryUtil.canTarget(card, target[0]) )
{
AllZone.GameAction.moveTo(hand ,target[0]);
}
AllZone.GameAction.sacrifice(getSourceCard());
}//resolve()
};//SpellAbility
ability.setDescription("U, Sacrifice AEther Spellbomb: Return target creature to its owner's hand.");
card.addSpellAbility(ability);
ability.setBeforePayMana(CardFactoryUtil.input_targetCreature(ability));
}
if(cardName.equals("Lifespark Spellbomb"))
{
final SpellAbility ability = new Ability_Activated(card, "G")
{
private static final long serialVersionUID = -5744842090293912606L;
public boolean canPlay()
{
return AllZone.GameAction.isCardInPlay(card)&&!AllZone.Stack.getSourceCards().contains(card);
}
public boolean canPlayAI()
{
CardList land = new CardList(AllZone.Computer_Play.getCards());
land = land.getType("Land");
CardList basic = land.getType("Basic");
if (basic.size() < 3) return false;
Card[] basic_1 = basic.toArray();
for(Card var : basic_1)
if (var.isTapped()) basic.remove(var);
basic.shuffle();
setTargetCard(basic.get(1));
return false;
}//canPlayAI()
public void resolve()
{
//in case ability is played twice
final int[] oldAttack = new int[1];
final int[] oldDefense = new int[1];
final Card card[] = new Card[1];
card[0] = getTargetCard();
oldAttack[0] = card[0].getBaseAttack();
oldDefense[0] = card[0].getBaseDefense();
card[0].setBaseAttack(3);
card[0].setBaseDefense(3);
card[0].addType("Creature");
//EOT
final Command untilEOT = new Command()
{
private static final long serialVersionUID = 7236360479349324099L;
public void execute()
{
card[0].setBaseAttack(oldAttack[0]);
card[0].setBaseDefense(oldDefense[0]);
card[0].removeType("Creature");
}
};
AllZone.EndOfTurn.addUntil(untilEOT);
AllZone.GameAction.sacrifice(getSourceCard());
}//resolve()
};//SpellAbility
card.addSpellAbility(ability);
ability.setDescription("G, Sacrifice Lifespark Spellbomb: Target land becomes a 3/3 Creature until end of turn. It is still a land.");
ability.setBeforePayMana(CardFactoryUtil.input_targetType(ability, "Land"));
}
if(cardName.equals("Pyrite Spellbomb"))
{
final SpellAbility ability = new Ability_Activated(card, "R")
{
/**
*
*/
private static final long serialVersionUID = 1L;
public boolean canPlay()
{
return AllZone.GameAction.isCardInPlay(card)&&!AllZone.Stack.getSourceCards().contains(card);
}
public boolean canPlayAI()
{
Random r = new Random();
if (r.nextFloat() <= Math.pow(.6667, card.getAbilityUsed()))
return true;
else
return false;
}
public void chooseTargetAI()
{
CardList list = CardFactoryUtil.AI_getHumanCreature(2, card, true);
list.shuffle();
if(list.isEmpty() || AllZone.Human_Life.getLife() < 5 + 2)
setTargetPlayer(Constant.Player.Human);
else
setTargetCard(list.get(0));
}//chooseTargetAI
public void resolve()
{
if(getTargetCard() != null)
{
if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) )
getTargetCard().addDamage(2);
}
else
AllZone.GameAction.getPlayerLife(getTargetPlayer()).subtractLife(2);
AllZone.GameAction.sacrifice(getSourceCard());
}//resolve()
};//Ability_Activated
ability.setBeforePayMana(CardFactoryUtil.input_targetCreaturePlayer(ability, true));
ability.setDescription("R, Sacrifice Pyrite Spellbomb: Pyrite Spellbomb deals 2 damage to target creature or player.");
card.addSpellAbility(ability);
}
if(cardName.equals("Sunbeam Spellbomb"))
{
final Ability ability = new Ability(card, "W")
{
public boolean canPlay()
{
return AllZone.GameAction.isCardInPlay(card)&&!AllZone.Stack.getSourceCards().contains(card);
}
public boolean canPlayAI()
{
return (AllZone.GameAction.getPlayerLife(Constant.Player.Computer).getLife() < 7);
}
public void resolve()
{
AllZone.GameAction.getPlayerLife(card.getController()).addLife(5);
AllZone.GameAction.sacrifice(getSourceCard());
}//resolve()
};//SpellAbility
ability.setStackDescription("You gain 5 life");
ability.setDescription("W, Sacrifice Sunbeam Spellbomb: You gain 5 life.");
card.addSpellAbility(ability);
}
if(cardName.equals("Necrogen Spellbomb"))
{
final Ability ability = new Ability(card, "B")
{
public boolean canPlay()
{
return AllZone.GameAction.isCardInPlay(card)&&!AllZone.Stack.getSourceCards().contains(card);
}
public boolean canPlayAI()
{
setTargetPlayer(Constant.Player.Human);
return (MyRandom.random.nextBoolean()&&AllZone.Human_Hand.size()>0);
}
public void resolve()
{
String s = getTargetPlayer();
setStackDescription("Necrogen Spellbomb - " +s +" discards a card");
if(Constant.Player.Computer.equals(getTargetPlayer()))
AllZone.GameAction.discardRandom(getTargetPlayer());
else
AllZone.InputControl.setInput(CardFactoryUtil.input_discard());
AllZone.GameAction.sacrifice(getSourceCard());
}//resolve()
};//SpellAbility
ability.setDescription("B, Sacrifice Necrogen Spellbomb: Target player discards a card");
ability.setBeforePayMana(CardFactoryUtil.input_targetPlayer(ability));
card.addSpellAbility(ability);
}
O forest, hold thy wand'ring son
Though fears assail the door.
O foliage, cloak thy ravaged one
In vestments cut for war.
--Eladamri, the Seed of Freyalise
Though fears assail the door.
O foliage, cloak thy ravaged one
In vestments cut for war.
--Eladamri, the Seed of Freyalise
- zerker2000
- Programmer
- Posts: 569
- Joined: 09 May 2009, 21:40
- Location: South Pasadena, CA
- Has thanked: 0 time
- Been thanked: 0 time
Re: CardFactory Cleaning
by Rob Cashwalker » 23 Jun 2009, 11:58
Two things -
One, this should be in its own post since it's new cards, not cleanup of CardFactory.
Second, I don't see any way for the Card Draw ability to be added to each of the cards. Typically when keywording an ability, you need to have a handler. One part of the handler returns the index in the keyword list, (should____) and the other (if (should_____ != -1)) usually deletes the keyword text and builds an ActivatedAbility object to do the action.
The way you've got it, you don't even need the keyword handler, but you do need to add both abilities to the card.
One, this should be in its own post since it's new cards, not cleanup of CardFactory.
Second, I don't see any way for the Card Draw ability to be added to each of the cards. Typically when keywording an ability, you need to have a handler. One part of the handler returns the index in the keyword list, (should____) and the other (if (should_____ != -1)) usually deletes the keyword text and builds an ActivatedAbility object to do the action.
The way you've got it, you don't even need the keyword handler, but you do need to add both abilities to the card.
The Force will be with you, Always.
-
Rob Cashwalker - Programmer
- Posts: 2167
- Joined: 09 Sep 2008, 15:09
- Location: New York
- Has thanked: 5 times
- Been thanked: 40 times
Re: CardFactory Cleaning
by zerker2000 » 23 Jun 2009, 12:13
oh oops sorry missed a piece (I copied the saproling one):
- Code: Select all
private final int shouldSpellbomb(Card c) {
ArrayList<String> a = c.getKeyword();
for (int i = 0; i < a.size(); i++)
if (a.get(i).toString().startsWith("1, Sacrifice"))//
if(a.get(i).equals("1, Sacrifice "+c.getName()+": Draw a card.")) return i;
return -1;
}
- Code: Select all
if (shouldSpellbomb(card) != -1)
{
int n = shouldSpellbomb(card);
if (n != -1)
{
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
card.addSpellAbility(CardFactoryUtil.ability_Spellbomb(card));
}
}//Spore Saproling
O forest, hold thy wand'ring son
Though fears assail the door.
O foliage, cloak thy ravaged one
In vestments cut for war.
--Eladamri, the Seed of Freyalise
Though fears assail the door.
O foliage, cloak thy ravaged one
In vestments cut for war.
--Eladamri, the Seed of Freyalise
- zerker2000
- Programmer
- Posts: 569
- Joined: 09 May 2009, 21:40
- Location: South Pasadena, CA
- Has thanked: 0 time
- Been thanked: 0 time
Re: CardFactory Cleaning
by zerker2000 » 25 Jun 2009, 07:26
I found a bunch of cards that had keyword pumping abilities that were implemented though "if(carrdName==<name>)":
Greater Forgeling should have PTPump 1 R:+3/-3 in cards.txt instead of a Cfactory name=.
Manta Riders and Killer Whale need KPump U: Flying put into cards.txt, and their ifcardname='es taken out
Goblin Ballon Brigade has the same problem, except with cost R
Sacromite myr needs to get KPump 2:Flying, and get the first ability and stuff affiliated with it taken out
Also, while talking of pumps, would it be possible to have a spKpump keyword similar to tgtKpump?
Greater Forgeling should have PTPump 1 R:+3/-3 in cards.txt instead of a Cfactory name=.
Manta Riders and Killer Whale need KPump U: Flying put into cards.txt, and their ifcardname='es taken out
Goblin Ballon Brigade has the same problem, except with cost R
Sacromite myr needs to get KPump 2:Flying, and get the first ability and stuff affiliated with it taken out
Also, while talking of pumps, would it be possible to have a spKpump keyword similar to tgtKpump?
O forest, hold thy wand'ring son
Though fears assail the door.
O foliage, cloak thy ravaged one
In vestments cut for war.
--Eladamri, the Seed of Freyalise
Though fears assail the door.
O foliage, cloak thy ravaged one
In vestments cut for war.
--Eladamri, the Seed of Freyalise
- zerker2000
- Programmer
- Posts: 569
- Joined: 09 May 2009, 21:40
- Location: South Pasadena, CA
- Has thanked: 0 time
- Been thanked: 0 time
Re: CardFactory Cleaning
by Rob Cashwalker » 25 Jun 2009, 11:57
I've pointed those out before....
Yeah, spPTPump, spKPump and spPTKPump are on my list.... I'm just about finished doing TgtPTPump.
On the topic of cleaning CardFactory, you should take a look at possible ways to split CardFactory into smaller, easier to maintain mini-factories. We have a thread here that shows what we've tried so far.
Yeah, spPTPump, spKPump and spPTKPump are on my list.... I'm just about finished doing TgtPTPump.
On the topic of cleaning CardFactory, you should take a look at possible ways to split CardFactory into smaller, easier to maintain mini-factories. We have a thread here that shows what we've tried so far.
The Force will be with you, Always.
-
Rob Cashwalker - Programmer
- Posts: 2167
- Joined: 09 Sep 2008, 15:09
- Location: New York
- Has thanked: 5 times
- Been thanked: 40 times
Re: CardFactory Cleaning
by zerker2000 » 26 Jun 2009, 06:08
Found the following in gilder bairn:
- Code: Select all
//badly written, hacky... TODO: should improve this
- Code: Select all
public void resolve()
{
Card c = getTargetCard();
card.untap();
if (c.sumAllCounters() == 0)
return;
else if (AllZone.GameAction.isCardInPlay(c) && CardFactoryUtil.canTarget(card, c))
for(Counters c_1 : Counters.values())
if (c.getCounters(c_1) != 0)
c.addCounter(c_1, c.getCounters(c_1));
}
O forest, hold thy wand'ring son
Though fears assail the door.
O foliage, cloak thy ravaged one
In vestments cut for war.
--Eladamri, the Seed of Freyalise
Though fears assail the door.
O foliage, cloak thy ravaged one
In vestments cut for war.
--Eladamri, the Seed of Freyalise
- zerker2000
- Programmer
- Posts: 569
- Joined: 09 May 2009, 21:40
- Location: South Pasadena, CA
- Has thanked: 0 time
- Been thanked: 0 time
Re: CardFactory Cleaning
by Hellfish » 26 Jun 2009, 10:19
Admittedly, my Java is rusty, and I can't seem to find the Counters class in the source but won't that result in an infinite loop?
Say
Say
- there is one counter on the target
- the loop goes through once
- there are now two counters
- the loop condition is checked, getting the newly placed token returned
- the loop goes through again and again, going through the new tokens as well
So now you're
Screaming for the blood of the cookie monster
Evil puppet demon of obesity
Time to change the tune of his fearful ballad
C is for "Lettuce," that's good enough for me
Screaming for the blood of the cookie monster
Evil puppet demon of obesity
Time to change the tune of his fearful ballad
C is for "Lettuce," that's good enough for me
-
Hellfish - Programmer
- Posts: 1297
- Joined: 07 Jun 2009, 10:41
- Location: South of the Pumphouse
- Has thanked: 110 times
- Been thanked: 169 times
Re: CardFactory Cleaning
by zerker2000 » 26 Jun 2009, 11:59
Erm no, Counters is an enum in Card.java, and c.addCounters and c.getCounters refer to an int<->Counters hashTable.
O forest, hold thy wand'ring son
Though fears assail the door.
O foliage, cloak thy ravaged one
In vestments cut for war.
--Eladamri, the Seed of Freyalise
Though fears assail the door.
O foliage, cloak thy ravaged one
In vestments cut for war.
--Eladamri, the Seed of Freyalise
- zerker2000
- Programmer
- Posts: 569
- Joined: 09 May 2009, 21:40
- Location: South Pasadena, CA
- Has thanked: 0 time
- Been thanked: 0 time
Re: CardFactory Cleaning
by Hellfish » 26 Jun 2009, 12:21
Ah... Heh.. Carry on.
So now you're
Screaming for the blood of the cookie monster
Evil puppet demon of obesity
Time to change the tune of his fearful ballad
C is for "Lettuce," that's good enough for me
Screaming for the blood of the cookie monster
Evil puppet demon of obesity
Time to change the tune of his fearful ballad
C is for "Lettuce," that's good enough for me
-
Hellfish - Programmer
- Posts: 1297
- Joined: 07 Jun 2009, 10:41
- Location: South of the Pumphouse
- Has thanked: 110 times
- Been thanked: 169 times
11 posts
• Page 1 of 1
Who is online
Users browsing this forum: flergeVes and 40 guests