Page 2 of 3

Re: Progress towards v0.7.1c

PostPosted: 03 Jul 2011, 01:26
by MageKing17
gumgod wrote:
Code: Select all
to.discard(random.to.hand.get())
I know we already sorted out the proper code for a random discard on IRC, but please never try random gibberish ever again. :/

Ricochet wrote:i used isSnowCoveredLand as designation but it doesnt exist
...because it would be completely redundant, considering Snow is just a supertype and you check for it like any other supertype... isLand.with_condition(lambda l: l.supertypes == Snow) works just fine.

I think I should really just add a method to the Player class for random discards so we don't have this problem. Like this:
Code: Select all
def random_discard(self, amount):
    if len(self.hand) > amount: return [self.discard(card) for card in random.sample(self.hand, amount)]
    else: return self.force_discard(-1)

Re: Progress towards v0.7.1c

PostPosted: 03 Jul 2011, 02:58
by gumgod
MageKing17 wrote:
gumgod wrote:
Code: Select all
to.discard(random.to.hand.get())
I know we already sorted out the proper code for a random discard on IRC, but please never try random gibberish ever again. :/
lol noted. To be fair though, I wasn't changing the version online, just trying on my own cards list. Trying stuff like this on my own list is how I learn, and how I figure out what works, and what doesn't.

MageKing17 wrote:I think I should really just add a method to the Player class for random discards so we don't have this problem. Like this:
Code: Select all
def random_discard(self, amount):
    if len(self.hand) > amount: return [self.discard(card) for card in random.sample(self.hand, amount)]
    else: return self.force_discard(-1)
This seems like a good idea. Would this also work for cost to activate/additional costs? (see http://gatherer.wizards.com/Pages/Searc ... Brandom%5D Draconian Cylix, coral helm and devastating dreams are good examples)

Edit: I also saw your change on Ivory Tower, and message on IRC. Good call, I didn't realize the game prevented a negative life gain so yea, I built in a check for it. I tested it your way, and it works as expected.

Re: Progress towards v0.7.1c

PostPosted: 04 Jul 2011, 16:33
by MageKing17
gumgod wrote:This seems like a good idea. Would this also work for cost to activate/additional costs?
Well, not by itself, obviously. You need a cost object to have a cost, and if we don't already have a DiscardAtRandomCost, then it needs to be added to the engine. Which we don't.

Mind you, I'm not sure if it should be a DiscardAtRandomCost, or a special form of DiscardCost. Like, DiscardCost(cardtype="random", number=2), or something (since it's not possible to have a random discard that's limited to a specific subset of cards).

Re: Progress towards v0.7.1c

PostPosted: 05 Jul 2011, 13:48
by Ricochet
MageKing17 wrote:
Ricochet wrote:i used isSnowCoveredLand as designation but it doesnt exist
...because it would be completely redundant, considering Snow is just a supertype and you check for it like any other supertype... isLand.with_condition(lambda l: l.supertypes == Snow) works just fine.
i tryed icequake that way and its causing dmg with any land as target...

Re: Progress towards v0.7.1c

PostPosted: 06 Jul 2011, 12:43
by gumgod
MageKing17 wrote:
gumgod wrote:This seems like a good idea. Would this also work for cost to activate/additional costs?
Well, not by itself, obviously. You need a cost object to have a cost, and if we don't already have a DiscardAtRandomCost, then it needs to be added to the engine. Which we don't.

Mind you, I'm not sure if it should be a DiscardAtRandomCost, or a special form of DiscardCost. Like, DiscardCost(cardtype="random", number=2), or something (since it's not possible to have a random discard that's limited to a specific subset of cards).
That looks fine to me. If you add it to the costs objects then it should be able to be used as any type of cost correct? (activated, additional cost to cast, alternative cost to cast ect)? Also I'd still like to see a life gain cost (for invigorate) that can target an opponent. :)

Edit: I tried Icequake this way, and it appears to work.
Code: Select all
name = 'Icequake'
cost = '1BB'
types = Sorcery
text = ["Destroy target land. If that land was a snow land, ~ deals 1 damage to that land's controller."]


#################################

@sorcery()
def ability():
    def effects(controller, source):
        cost = yield source.cost
        target = yield Target(isLand)
        target.destroy()
        if target.supertypes == Snow: source.deal_damage(target.controller,1)
        yield
    return effects
abilities.add(ability)

Re: Progress towards v0.7.1c

PostPosted: 06 Jul 2011, 22:28
by Ricochet
is there a way to make an static doesnt untap effect like in meekstone and winter orb?
also, how to make black vise's triggered effect use the target from the enterbattlefield effect?

Re: Progress towards v0.7.1c

PostPosted: 07 Jul 2011, 14:48
by MageKing17
Ricochet wrote:is there a way to make an static doesnt untap effect like in meekstone and winter orb?
Yes. For Meekstone, see the version I just uploaded. I haven't tested it, but it should work.

Ricochet wrote:also, how to make black vise's triggered effect use the target from the enterbattlefield effect?
By pretending Incantus handles linked abilities, of course. :P

Here is as close to the rules as the card can currently come.

Re: Progress towards v0.7.1c

PostPosted: 07 Jul 2011, 16:21
by gumgod
MageKing17 wrote:
Ricochet wrote:is there a way to make an static doesnt untap effect like in meekstone and winter orb?
Yes. For Meekstone, see the version I just uploaded. I haven't tested it, but it should work.

Ricochet wrote:also, how to make black vise's triggered effect use the target from the enterbattlefield effect?
By pretending Incantus handles linked abilities, of course. :P

Here is as close to the rules as the card can currently come.
Looking at your meekstone, it appears to work correctly from minimal testing. I'm curious though about cards like winter orb, and smoke. Would you program them like rising waters where there is a trigger at the beginning of the upkeep? or more accurately the untap step (more accurate for smoke and winter orb)? and if so how would you keep that trigger from being countered with stifle (assuming stifle gets implemented) I know there's a this_card_cant_be_countered(), but is there something like that for a triggered ability (ie: this_ability_cant_be_countered())?

Re: Progress towards v0.7.1c

PostPosted: 10 Jul 2011, 14:41
by MageKing17
gumgod wrote:I'm curious though about cards like winter orb, and smoke. Would you program them like rising waters where there is a trigger at the beginning of the upkeep? or more accurately the untap step (more accurate for smoke and winter orb)? and if so how would you keep that trigger from being countered with stifle (assuming stifle gets implemented) I know there's a this_card_cant_be_countered(), but is there something like that for a triggered ability (ie: this_ability_cant_be_countered())?
Winter Orb and Smoke are not triggered abilities, and therefore should never be implemented as though they were.

In v0.591, Winter Orb was implemented with the following ability:
Code: Select all
@static(txt=text[0])
def ability():
    def effects(source):
        def checkUntapStep(self, cards):
            if not source.tapped:
                return len([True for card in cards if isLand(card)]) <= 1
            else: return True
        yield do_override(Player, 'checkUntapStep', checkUntapStep)
    return no_condition, effects
abilities.add(ability)
I think this ability will still work verbatim. Try it out.

(Your homework, dear children, is to make the single change needed to turn this into Smoke's ability.)

EDIT: Just noticed that I apparently forgot to save Black Vise. Look again.

Re: Progress towards v0.7.1c

PostPosted: 13 Jul 2011, 11:32
by gumgod
MageKing17 wrote:
gumgod wrote:I'm curious though about cards like winter orb, and smoke. Would you program them like rising waters where there is a trigger at the beginning of the upkeep? or more accurately the untap step (more accurate for smoke and winter orb)? and if so how would you keep that trigger from being countered with stifle (assuming stifle gets implemented) I know there's a this_card_cant_be_countered(), but is there something like that for a triggered ability (ie: this_ability_cant_be_countered())?
Winter Orb and Smoke are not triggered abilities, and therefore should never be implemented as though they were.

In v0.591, Winter Orb was implemented with the following ability:
Code: Select all
@static(txt=text[0])
def ability():
    def effects(source):
        def checkUntapStep(self, cards):
            if not source.tapped:
                return len([True for card in cards if isLand(card)]) <= 1
            else: return True
        yield do_override(Player, 'checkUntapStep', checkUntapStep)
    return no_condition, effects
abilities.add(ability)
I think this ability will still work verbatim. Try it out.

(Your homework, dear children, is to make the single change needed to turn this into Smoke's ability.)

EDIT: Just noticed that I apparently forgot to save Black Vise. Look again.
There's actually two changes needed here. Winter orb no longer turns off when tapped, and smoke would never turn off when tapped, so that if clause has got to go. ;) Other than that, changing isLand to isCreature should make it work. I'll try it out if I have a chance to today.

Re: Progress towards v0.7.1c

PostPosted: 16 Jul 2011, 21:09
by Ricochet
Black Vise is working perfectly(thx MageKing), i made The Rack using the same logic with an if clause to trigger when the player has less than 3 cards in hand(to avoid negative values)and it seems to work ok(i didnt post the code cause im typing from cell phone). The "winter orb homework" made me feel stupid(cause i couldnt make it work) so i wondered through a hole different universe of cards and got stuck in Undiscovered Paradise...
i tryed
Code: Select all
replace(source, "CanUntapDuringUntapStep", source move_to("hand"))
but it moves instantaneously to hand, cant figure how to make it move only during the controllers next untap step after been used.

the problem with winter orb was on my incantus instalation, reinstaled and it works now.

Re: Progress towards v0.7.1c

PostPosted: 17 Jul 2011, 21:41
by MageKing17
Ricochet wrote:Black Vise is working perfectly(thx MageKing), i made The Rack using the same logic with an if clause to trigger when the player has less than 3 cards in hand(to avoid negative values)and it seems to work ok(i didnt post the code cause im typing from cell phone).
Don't perform negative-value checks for damage or lifeloss. The inability to take negative damage or lose negative life is a game rule, and is therefore handled by the game engine; having a check in the card is a waste of text and processing time, and would be inaccurate if that rule were to ever change (not that I expect it to; it's the principle of the thing).

Ricochet wrote:The "winter orb homework" made me feel stupid(cause i couldnt make it work) so i wondered through a hole different universe of cards and got stuck in Undiscovered Paradise...
i tryed
Code: Select all
replace(source, "CanUntapDuringUntapStep", source move_to("hand"))
but it moves instantaneously to hand, cant figure how to make it move only during the controllers next untap step after been used.
...What. No. That is not how replacement effects work. At all. You need to make a function that takes the place of source.CanUntapDuringUntapStep, not just give it an instruction. It moves immediately because you are telling it to move immediately.

...Also, Undiscovered Paradise isn't a replacement effect on CanUntapDuringUntapStep, it's a replacement effect on the untap step itself. I'll implement it so you can see how it's supposed to work.

Re: Progress towards v0.7.1c

PostPosted: 19 Jul 2011, 15:22
by Ricochet
the Thundering Wurm on the web editor wasnt working, so i came up with this
Code: Select all
@triggered(txt=text[0])
def ability():
    def effects(controller, source):
        target = yield NoTarget()
        if controller.you_may("discard a land card"):
            card = controller.choose_from(controller.hand.get(), 1, cardtype=isLandCard)
            controller.discard(card)
        else: source.destroy()
        yield
    return EnterTrigger("battlefield", source_match), effects
abilities.add(ability)
or
Code: Select all
@triggered(txt=text[0])
def ability():
    def effects(controller, source):
        target = yield NoTarget()
        if controller.you_may("discard a land card"):
            card = controller.choose_from(controller.hand.get(), 1, cardtype=isLandCard)
            controller.discard(card)
        else: controller.sacrifice(source)
        yield
    return EnterTrigger("battlefield", source_match), effects
abilities.add(ability)
i dont know wich has got the right rules for this card(destroy or sacrifice), so any1 with access to the web editor(and who knows wich one is the right version) would please make the change...

Re: Progress towards v0.7.1c

PostPosted: 19 Jul 2011, 16:10
by Ricochet
and now a working Balduvian Horde
Code: Select all
name = 'Balduvian Horde'
cost = '2RR'
types = Creature
subtypes = Human, Barbarian
power = 5
toughness = 5
text = ['When ~ enters the battlefield, sacrifice it unless you discard a card at random.']

#################################

@triggered(txt=text[0])
def ability():
    def effects(controller, source):
        target = yield NoTarget()
        import random
        if controller.you_may("discard a card at random"):
            [controller.discard(card) for card in random.sample(controller.hand, 1)]
        else: controller.sacrifice(source)
        yield
    return EnterTrigger("battlefield", source_match), effects
abilities.add(ability)

--------------- Balduvian Horde

Re: Progress towards v0.7.1c

PostPosted: 19 Jul 2011, 17:15
by MageKing17
Ricochet wrote:the Thundering Wurm on the web editor wasnt working, so i came up with this
Code: Select all
@triggered(txt=text[0])
def ability():
    def effects(controller, source):
        target = yield NoTarget()
        if controller.you_may("discard a land card"):
            card = controller.choose_from(controller.hand.get(), 1, cardtype=isLandCard)
            controller.discard(card)
        else: source.destroy()
        yield
    return EnterTrigger("battlefield", source_match), effects
abilities.add(ability)
or
Code: Select all
@triggered(txt=text[0])
def ability():
    def effects(controller, source):
        target = yield NoTarget()
        if controller.you_may("discard a land card"):
            card = controller.choose_from(controller.hand.get(), 1, cardtype=isLandCard)
            controller.discard(card)
        else: controller.sacrifice(source)
        yield
    return EnterTrigger("battlefield", source_match), effects
abilities.add(ability)
i dont know wich has got the right rules for this card(destroy or sacrifice), so any1 with access to the web editor(and who knows wich one is the right version) would please make the change...
Actually, Mat's solution was an elegant implementation that was merely missing four letters ("Card", BTW). But good for you to notice it wasn't working; at least somebody's testing cards.

Technically, I suppose, Mat's solution is incorrect because it's not actually paying a cost, which could theoretically come back to bite us in the ass, but I can't think of anything that could care about a cost paid in the middle of a triggered ability's activation. Usually, abilities just care about costs paid to cast spells or activate abilities.

Ricochet wrote:and now a working Balduvian Horde
Code: Select all
name = 'Balduvian Horde'
cost = '2RR'
types = Creature
subtypes = Human, Barbarian
power = 5
toughness = 5
text = ['When ~ enters the battlefield, sacrifice it unless you discard a card at random.']

#################################

@triggered(txt=text[0])
def ability():
    def effects(controller, source):
        target = yield NoTarget()
        import random
        if controller.you_may("discard a card at random"):
            [controller.discard(card) for card in random.sample(controller.hand, 1)]
        else: controller.sacrifice(source)
        yield
    return EnterTrigger("battlefield", source_match), effects
abilities.add(ability)

--------------- Balduvian Horde
Actually, that doesn't quite work. If you choose to discard a card but have no cards in your hand, under your implementation, Balduvian Horde would live, despite the fact that it needs to be sacrificed in that case. Also, your use of list comprehension and random.sample is redundant when you're only picking one card. Here is how the card should look.

But thank you for testing cards and coming up with code; if you want access to the web editor, PM me your email address.