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() { ...@@ -1995,10 +1995,10 @@ void card::filter_disable_related_cards() {
} }
// put all summon procedures except ordinay summon in peset (see is_can_be_summoned()) // put all summon procedures except ordinay summon in peset (see is_can_be_summoned())
// return value: // return value:
// -2 = this has EFFECT_LIMIT_SUMMON_PROC, 0 available // -2 = this has a EFFECT_LIMIT_SUMMON_PROC, 0 available
// -1 = this has EFFECT_LIMIT_SUMMON_PROC, at least 1 available // -1 = this has a EFFECT_LIMIT_SUMMON_PROC, at least 1 available
// 0 = no EFFECT_LIMIT_SUMMON_PROC, no available EFFECT_SUMMON_PROC // 0 = no EFFECT_LIMIT_SUMMON_PROC, and ordinary summon ia not available
// 1 = no EFFECT_LIMIT_SUMMON_PROC, at least 1 available EFFECT_SUMMON_PROC // 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) { int32 card::filter_summon_procedure(uint8 playerid, effect_set* peset, uint8 ignore_count, uint8 min_tribute) {
effect_set eset; effect_set eset;
uint8 toplayer; uint8 toplayer;
...@@ -2012,6 +2012,7 @@ int32 card::filter_summon_procedure(uint8 playerid, effect_set* peset, uint8 ign ...@@ -2012,6 +2012,7 @@ int32 card::filter_summon_procedure(uint8 playerid, effect_set* peset, uint8 ign
toplayer = 1 - playerid; toplayer = 1 - playerid;
} else } else
toplayer = playerid; toplayer = playerid;
// the script will check min_tribute, Duel.CheckTribute()
if(eset[i]->check_count_limit(playerid) && is_summonable(eset[i], min_tribute) 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->check_unique_onfield(this, toplayer, LOCATION_MZONE)
&& pduel->game_field->is_player_can_summon(eset[i]->get_value(this), playerid, this)) && 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 ...@@ -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)) && pduel->game_field->is_player_can_summon(eset[i]->get_value(this), playerid, this))
peset->add_item(eset[i]); peset->add_item(eset[i]);
} }
// ordinary summon
if(!pduel->game_field->is_player_can_summon(SUMMON_TYPE_NORMAL, playerid, this)) if(!pduel->game_field->is_player_can_summon(SUMMON_TYPE_NORMAL, playerid, this))
return FALSE; return FALSE;
if(pduel->game_field->check_unique_onfield(this, playerid, LOCATION_MZONE)) 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 ...@@ -2045,10 +2047,10 @@ int32 card::filter_summon_procedure(uint8 playerid, effect_set* peset, uint8 ign
int32 min = rcount & 0xffff, max = (rcount >> 16) & 0xffff; int32 min = rcount & 0xffff, max = (rcount >> 16) & 0xffff;
if(!pduel->game_field->is_player_can_summon(SUMMON_TYPE_ADVANCE, playerid, this)) if(!pduel->game_field->is_player_can_summon(SUMMON_TYPE_ADVANCE, playerid, this))
max = 0; max = 0;
if(max < min_tribute)
return FALSE;
if(min < min_tribute) if(min < min_tribute)
min = min_tribute; min = min_tribute;
if(max < min)
return FALSE;
return pduel->game_field->check_tribute(this, min, max, 0, current.controler); 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()) // 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 ...@@ -2078,10 +2080,10 @@ int32 card::filter_set_procedure(uint8 playerid, effect_set* peset, uint8 ignore
int32 min = rcount & 0xffff, max = (rcount >> 16) & 0xffff; int32 min = rcount & 0xffff, max = (rcount >> 16) & 0xffff;
if(!pduel->game_field->is_player_can_mset(SUMMON_TYPE_ADVANCE, playerid, this)) if(!pduel->game_field->is_player_can_mset(SUMMON_TYPE_ADVANCE, playerid, this))
max = 0; max = 0;
if(max < min_tribute)
return FALSE;
if(min < min_tribute) if(min < min_tribute)
min = min_tribute; min = min_tribute;
if(max < min)
return FALSE;
return pduel->game_field->check_tribute(this, min, max, 0, current.controler); 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) { 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) { ...@@ -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 // if this does not have a summon procedure, it will check ordinary summon
// ignore_count: ignore the summon count in this turn or not // 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 // min_tribute: the limit of min tribute number by EFFECT_EXTRA_SUMMON_COUNT
// return: whether playerid can summon this or not // return: whether playerid can summon this or not
int32 card::is_can_be_summoned(uint8 playerid, uint8 ignore_count, effect* peffect, uint8 min_tribute) { int32 card::is_can_be_summoned(uint8 playerid, uint8 ignore_count, effect* peffect, uint8 min_tribute) {
...@@ -2388,12 +2390,19 @@ int32 card::is_can_be_summoned(uint8 playerid, uint8 ignore_count, effect* peffe ...@@ -2388,12 +2390,19 @@ int32 card::is_can_be_summoned(uint8 playerid, uint8 ignore_count, effect* peffe
} }
effect_set proc; effect_set proc;
int32 res = filter_summon_procedure(playerid, &proc, ignore_count, min_tribute); int32 res = filter_summon_procedure(playerid, &proc, ignore_count, min_tribute);
if((peffect && res < 0) || (!peffect && (!res || res == -2) && !proc.size()) if(peffect) {
|| (peffect && (proc.size() == 0) && !pduel->game_field->is_player_can_summon(peffect->get_value(), playerid, this))) { 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(); pduel->game_field->restore_lp_cost();
return FALSE; return FALSE;
} }
} }
}
pduel->game_field->restore_lp_cost(); pduel->game_field->restore_lp_cost();
return TRUE; return TRUE;
} }
...@@ -2609,11 +2618,18 @@ int32 card::is_setable_mzone(uint8 playerid, uint8 ignore_count, effect* peffect ...@@ -2609,11 +2618,18 @@ int32 card::is_setable_mzone(uint8 playerid, uint8 ignore_count, effect* peffect
} }
eset.clear(); eset.clear();
int32 res = filter_set_procedure(playerid, &eset, ignore_count, min_tribute); int32 res = filter_set_procedure(playerid, &eset, ignore_count, min_tribute);
if((peffect && res < 0) || (!peffect && (!res || res == -2) && !eset.size()) if(peffect) {
|| (peffect && (eset.size() == 0) && !pduel->game_field->is_player_can_mset(peffect->get_value(), playerid, this))) { 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(); pduel->game_field->restore_lp_cost();
return FALSE; return FALSE;
} }
}
pduel->game_field->restore_lp_cost(); pduel->game_field->restore_lp_cost();
return TRUE; return TRUE;
} }
......
...@@ -1323,7 +1323,6 @@ int32 field::get_summon_release_olist(card* target, card_set* ex_list, card_set* ...@@ -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) { int32 field::get_summon_release_exlist(card* target, card_set* ex_list, group* mg) {
uint8 p = target->current.controler; uint8 p = target->current.controler;
card* pcard; card* pcard;
uint32 rcount = 0;
for(int i = 0; i < 5; ++i) { for(int i = 0; i < 5; ++i) {
pcard = player[1 - p].list_mzone[i]; pcard = player[1 - p].list_mzone[i];
if(!(pcard && pcard->is_releasable_by_summon(p, target))) 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 ...@@ -1332,14 +1331,9 @@ int32 field::get_summon_release_exlist(card* target, card_set* ex_list, group* m
continue; continue;
if(pcard->is_affected_by_effect(EFFECT_EXTRA_RELEASE)) { if(pcard->is_affected_by_effect(EFFECT_EXTRA_RELEASE)) {
ex_list->insert(pcard); 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) { int32 field::get_summon_count_limit(uint8 playerid) {
effect_set eset; effect_set eset;
...@@ -2225,6 +2219,7 @@ int32 field::check_tuner_material(card* pcard, card* tuner, int32 findex1, int32 ...@@ -2225,6 +2219,7 @@ int32 field::check_tuner_material(card* pcard, card* tuner, int32 findex1, int32
pduel->restore_assumes(); pduel->restore_assumes();
return FALSE; return FALSE;
} }
// check if "releasing min~max tributes" is available
int32 field::check_tribute(card* pcard, int32 min, int32 max, group* mg, uint8 toplayer) { int32 field::check_tribute(card* pcard, int32 min, int32 max, group* mg, uint8 toplayer) {
card_set test, exset; card_set test, exset;
int32 m1 = 0, m2 = 0; int32 m1 = 0, m2 = 0;
...@@ -2241,22 +2236,29 @@ int32 field::check_tribute(card* pcard, int32 min, int32 max, group* mg, uint8 t ...@@ -2241,22 +2236,29 @@ int32 field::check_tribute(card* pcard, int32 min, int32 max, group* mg, uint8 t
if(min > max) if(min > max)
return FALSE; return FALSE;
int32 fcount = get_useable_count(toplayer, LOCATION_MZONE, pcard->current.controler, LOCATION_REASON_TOFIELD); int32 fcount = get_useable_count(toplayer, LOCATION_MZONE, pcard->current.controler, LOCATION_REASON_TOFIELD);
// test "releasing i tributes"
for(int32 i = min; i <= max; ++i){
int32 rmax = 0;
if(toplayer == pcard->current.controler) { if(toplayer == pcard->current.controler) {
uint32 rmax = get_summon_release_exlist(pcard, &exset, mg); get_summon_release_exlist(pcard, &exset, mg);
uint32 rmin = exset.size(); // let r be the number of monsters released from mzone of toplayer
min -= rmax; // r<=i-ex, r<=test
max -= rmin; // rmax = min{i-ex, test}
if(i >= (int32)exset.size()){
rmax = i - (int32)exset.size();
if(rmax > (int32)test.size())
rmax = (int32)test.size();
} }
if(min <= 0 && max <= 0) { else
if(fcount <= 0) rmax = 0;
return FALSE;
} else {
if((int32)test.size() < -fcount + 1)
return FALSE;
if(max < -fcount + 1)
return FALSE;
} }
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) { int32 field::check_with_sum_limit(const card_vector& mats, int32 acc, int32 index, int32 count, int32 min, int32 max) {
if(count > 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