Commit 4876b949 authored by salix5's avatar salix5

summon check

Duel.CheckTribute()
Now it will check if there exist min<=i<=max such that releasing i tributes is possible.
(Note that relaesing k tributes is different from releasing k monsters,
since some monsters can be treated as 2 or more monsters)
The proof of correctness is shown below.

field::get_summon_release_exlist()
This function is just a support function of check_tribute(), and now it will not modify release_param.

card::is_can_be_summoned()
The aegument peffect is a special case used by effects that change theordinary summon procedure (c80921533),
and now it is seperated from normal cases.

TODO:
check min_tribute in scripts
Duel.CheckTribute(c,k,k)
parent 5a311849
......@@ -1995,10 +1995,10 @@ void card::filter_disable_related_cards() {
}
// put all summon procedures except ordinay summon in peset (see is_can_be_summoned())
// return value:
// -2 = this has EFFECT_LIMIT_SUMMON_PROC, 0 available
// -1 = this has EFFECT_LIMIT_SUMMON_PROC, at least 1 available
// 0 = no EFFECT_LIMIT_SUMMON_PROC, no available EFFECT_SUMMON_PROC
// 1 = no EFFECT_LIMIT_SUMMON_PROC, at least 1 available EFFECT_SUMMON_PROC
// -2 = this has a EFFECT_LIMIT_SUMMON_PROC, 0 available
// -1 = this has a EFFECT_LIMIT_SUMMON_PROC, at least 1 available
// 0 = no EFFECT_LIMIT_SUMMON_PROC, and ordinary summon ia not available
// 1 = no EFFECT_LIMIT_SUMMON_PROC, and ordinary summon ia available
int32 card::filter_summon_procedure(uint8 playerid, effect_set* peset, uint8 ignore_count, uint8 min_tribute) {
effect_set eset;
uint8 toplayer;
......@@ -2012,6 +2012,7 @@ int32 card::filter_summon_procedure(uint8 playerid, effect_set* peset, uint8 ign
toplayer = 1 - playerid;
} else
toplayer = playerid;
// the script will check min_tribute, Duel.CheckTribute()
if(eset[i]->check_count_limit(playerid) && is_summonable(eset[i], min_tribute)
&& !pduel->game_field->check_unique_onfield(this, toplayer, LOCATION_MZONE)
&& pduel->game_field->is_player_can_summon(eset[i]->get_value(this), playerid, this))
......@@ -2037,6 +2038,7 @@ int32 card::filter_summon_procedure(uint8 playerid, effect_set* peset, uint8 ign
&& pduel->game_field->is_player_can_summon(eset[i]->get_value(this), playerid, this))
peset->add_item(eset[i]);
}
// ordinary summon
if(!pduel->game_field->is_player_can_summon(SUMMON_TYPE_NORMAL, playerid, this))
return FALSE;
if(pduel->game_field->check_unique_onfield(this, playerid, LOCATION_MZONE))
......@@ -2045,10 +2047,10 @@ int32 card::filter_summon_procedure(uint8 playerid, effect_set* peset, uint8 ign
int32 min = rcount & 0xffff, max = (rcount >> 16) & 0xffff;
if(!pduel->game_field->is_player_can_summon(SUMMON_TYPE_ADVANCE, playerid, this))
max = 0;
if(max < min_tribute)
return FALSE;
if(min < min_tribute)
min = min_tribute;
if(max < min)
return FALSE;
return pduel->game_field->check_tribute(this, min, max, 0, current.controler);
}
// put all set procedures except ordinay set in peset (see is_can_be_summoned())
......@@ -2078,10 +2080,10 @@ int32 card::filter_set_procedure(uint8 playerid, effect_set* peset, uint8 ignore
int32 min = rcount & 0xffff, max = (rcount >> 16) & 0xffff;
if(!pduel->game_field->is_player_can_mset(SUMMON_TYPE_ADVANCE, playerid, this))
max = 0;
if(max < min_tribute)
return FALSE;
if(min < min_tribute)
min = min_tribute;
if(max < min)
return FALSE;
return pduel->game_field->check_tribute(this, min, max, 0, current.controler);
}
void card::filter_spsummon_procedure(uint8 playerid, effect_set* peset, uint32 summon_type) {
......@@ -2340,7 +2342,7 @@ int32 card::is_summonable(effect* peffect, uint8 min_tribute) {
}
// if this does not have a summon procedure, it will check ordinary summon
// ignore_count: ignore the summon count in this turn or not
// peffect: effects that changes the ordinary summon procedure (c80921533)
// peffect: effects that change the ordinary summon procedure (c80921533)
// min_tribute: the limit of min tribute number by EFFECT_EXTRA_SUMMON_COUNT
// return: whether playerid can summon this or not
int32 card::is_can_be_summoned(uint8 playerid, uint8 ignore_count, effect* peffect, uint8 min_tribute) {
......@@ -2388,10 +2390,17 @@ int32 card::is_can_be_summoned(uint8 playerid, uint8 ignore_count, effect* peffe
}
effect_set proc;
int32 res = filter_summon_procedure(playerid, &proc, ignore_count, min_tribute);
if((peffect && res < 0) || (!peffect && (!res || res == -2) && !proc.size())
|| (peffect && (proc.size() == 0) && !pduel->game_field->is_player_can_summon(peffect->get_value(), playerid, this))) {
pduel->game_field->restore_lp_cost();
return FALSE;
if(peffect) {
if(res < 0 || !pduel->game_field->is_player_can_summon(peffect->get_value(), playerid, this)){
pduel->game_field->restore_lp_cost();
return FALSE;
}
}
else {
if(!proc.size() && res == 0) {
pduel->game_field->restore_lp_cost();
return FALSE;
}
}
}
pduel->game_field->restore_lp_cost();
......@@ -2609,10 +2618,17 @@ int32 card::is_setable_mzone(uint8 playerid, uint8 ignore_count, effect* peffect
}
eset.clear();
int32 res = filter_set_procedure(playerid, &eset, ignore_count, min_tribute);
if((peffect && res < 0) || (!peffect && (!res || res == -2) && !eset.size())
|| (peffect && (eset.size() == 0) && !pduel->game_field->is_player_can_mset(peffect->get_value(), playerid, this))) {
pduel->game_field->restore_lp_cost();
return FALSE;
if(peffect) {
if(res < 0 || !pduel->game_field->is_player_can_mset(peffect->get_value(), playerid, this)){
pduel->game_field->restore_lp_cost();
return FALSE;
}
}
else {
if(!eset.size() && res == 0) {
pduel->game_field->restore_lp_cost();
return FALSE;
}
}
pduel->game_field->restore_lp_cost();
return TRUE;
......
......@@ -1323,7 +1323,6 @@ int32 field::get_summon_release_olist(card* target, card_set* ex_list, card_set*
int32 field::get_summon_release_exlist(card* target, card_set* ex_list, group* mg) {
uint8 p = target->current.controler;
card* pcard;
uint32 rcount = 0;
for(int i = 0; i < 5; ++i) {
pcard = player[1 - p].list_mzone[i];
if(!(pcard && pcard->is_releasable_by_summon(p, target)))
......@@ -1332,14 +1331,9 @@ int32 field::get_summon_release_exlist(card* target, card_set* ex_list, group* m
continue;
if(pcard->is_affected_by_effect(EFFECT_EXTRA_RELEASE)) {
ex_list->insert(pcard);
if(pcard->is_affected_by_effect(EFFECT_DOUBLE_TRIBUTE, target))
pcard->release_param = 2;
else
pcard->release_param = 1;
rcount += pcard->release_param;
}
}
return rcount;
return TRUE;
}
int32 field::get_summon_count_limit(uint8 playerid) {
effect_set eset;
......@@ -2225,6 +2219,7 @@ int32 field::check_tuner_material(card* pcard, card* tuner, int32 findex1, int32
pduel->restore_assumes();
return FALSE;
}
// check if "releasing min~max tributes" is available
int32 field::check_tribute(card* pcard, int32 min, int32 max, group* mg, uint8 toplayer) {
card_set test, exset;
int32 m1 = 0, m2 = 0;
......@@ -2241,22 +2236,29 @@ int32 field::check_tribute(card* pcard, int32 min, int32 max, group* mg, uint8 t
if(min > max)
return FALSE;
int32 fcount = get_useable_count(toplayer, LOCATION_MZONE, pcard->current.controler, LOCATION_REASON_TOFIELD);
if(toplayer == pcard->current.controler) {
uint32 rmax = get_summon_release_exlist(pcard, &exset, mg);
uint32 rmin = exset.size();
min -= rmax;
max -= rmin;
}
if(min <= 0 && max <= 0) {
if(fcount <= 0)
return FALSE;
} else {
if((int32)test.size() < -fcount + 1)
return FALSE;
if(max < -fcount + 1)
return FALSE;
// test "releasing i tributes"
for(int32 i = min; i <= max; ++i){
int32 rmax = 0;
if(toplayer == pcard->current.controler) {
get_summon_release_exlist(pcard, &exset, mg);
// let r be the number of monsters released from mzone of toplayer
// r<=i-ex, r<=test
// rmax = min{i-ex, test}
if(i >= (int32)exset.size()){
rmax = i - (int32)exset.size();
if(rmax > (int32)test.size())
rmax = (int32)test.size();
}
else
rmax = 0;
}
else
rmax = (int32)test.size();
// this is the # of slots after the advance summon
if(fcount + rmax - 1 >= 0)
return TRUE;
}
return TRUE;
return FALSE;
}
int32 field::check_with_sum_limit(const card_vector& mats, int32 acc, int32 index, int32 count, int32 min, int32 max) {
if(count > max)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment