Commit a3465f5b authored by DailyShana's avatar DailyShana Committed by GitHub

new ruling (#294)

* new trap monster rule

* new ruling of special summon once

* new ruling of (special) summon count in oath

* new ruling of trigger effect

trigger effect cannot be activated if the card is moved to other place

* update (extra) deck effect handling

including new rule that effect of face down card in extra deck cannot be activated unless explicitly written

* new trap monster rule: changing to face down

* new trap monster rule: disabled

* fix changing to face down of trap monster
parent 9974cf8f
...@@ -3593,7 +3593,8 @@ int32 card::is_control_can_be_changed(int32 ignore_mzone, uint32 zone) { ...@@ -3593,7 +3593,8 @@ int32 card::is_control_can_be_changed(int32 ignore_mzone, uint32 zone) {
return FALSE; return FALSE;
if(!ignore_mzone && pduel->game_field->get_useable_count(this, 1 - current.controler, LOCATION_MZONE, current.controler, LOCATION_REASON_CONTROL, zone) <= 0) if(!ignore_mzone && pduel->game_field->get_useable_count(this, 1 - current.controler, LOCATION_MZONE, current.controler, LOCATION_REASON_CONTROL, zone) <= 0)
return FALSE; return FALSE;
if((get_type() & TYPE_TRAPMONSTER) && pduel->game_field->get_useable_count(this, 1 - current.controler, LOCATION_SZONE, current.controler, LOCATION_REASON_CONTROL) <= 0) if(pduel->game_field->core.duel_rule <= 4 && (get_type() & TYPE_TRAPMONSTER)
&& pduel->game_field->get_useable_count(this, 1 - current.controler, LOCATION_SZONE, current.controler, LOCATION_REASON_CONTROL) <= 0)
return FALSE; return FALSE;
if(is_affected_by_effect(EFFECT_CANNOT_CHANGE_CONTROL)) if(is_affected_by_effect(EFFECT_CANNOT_CHANGE_CONTROL))
return FALSE; return FALSE;
......
...@@ -278,6 +278,13 @@ int32 effect::is_activateable(uint8 playerid, const tevent& e, int32 neglect_con ...@@ -278,6 +278,13 @@ int32 effect::is_activateable(uint8 playerid, const tevent& e, int32 neglect_con
} }
if(phandler->current.location == LOCATION_OVERLAY) if(phandler->current.location == LOCATION_OVERLAY)
return FALSE; return FALSE;
if(phandler->current.location == LOCATION_DECK
|| pduel->game_field->core.duel_rule >= 5 && phandler->current.location == LOCATION_EXTRA && (phandler->current.position & POS_FACEDOWN)) {
if((type & EFFECT_TYPE_SINGLE) && code != EVENT_TO_DECK)
return FALSE;
if((type & EFFECT_TYPE_FIELD) && !(range & (LOCATION_DECK | LOCATION_EXTRA)))
return FALSE;
}
if((type & EFFECT_TYPE_FIELD) && (phandler->current.controler != playerid) && !is_flag(EFFECT_FLAG_BOTH_SIDE | EFFECT_FLAG_EVENT_PLAYER)) if((type & EFFECT_TYPE_FIELD) && (phandler->current.controler != playerid) && !is_flag(EFFECT_FLAG_BOTH_SIDE | EFFECT_FLAG_EVENT_PLAYER))
return FALSE; return FALSE;
if(phandler->is_status(STATUS_FORBIDDEN)) if(phandler->is_status(STATUS_FORBIDDEN))
......
...@@ -3368,19 +3368,6 @@ int32 field::check_cteffect_hint(effect* peffect, uint8 playerid) { ...@@ -3368,19 +3368,6 @@ int32 field::check_cteffect_hint(effect* peffect, uint8 playerid) {
} }
return FALSE; return FALSE;
} }
int32 field::check_deck_effect(chain& ch) const {
effect* peffect = ch.triggering_effect;
card* phandler = peffect->get_handler();
if(!peffect->is_flag(EFFECT_FLAG_FIELD_ONLY)
&& ch.triggering_location == LOCATION_DECK && (phandler->current.location & LOCATION_DECK)) {
if((peffect->type & EFFECT_TYPE_SINGLE) && !peffect->is_flag(EFFECT_FLAG_SINGLE_RANGE)
&& peffect->code == EVENT_TO_DECK || (peffect->range & LOCATION_DECK)) {
ch.flag |= CHAIN_DECK_EFFECT;
} else
return FALSE;
}
return TRUE;
}
int32 field::check_hand_trigger(chain& ch) { int32 field::check_hand_trigger(chain& ch) {
effect* peffect = ch.triggering_effect; effect* peffect = ch.triggering_effect;
card* phandler = peffect->get_handler(); card* phandler = peffect->get_handler();
...@@ -3396,23 +3383,6 @@ int32 field::check_hand_trigger(chain& ch) { ...@@ -3396,23 +3383,6 @@ int32 field::check_hand_trigger(chain& ch) {
} }
return TRUE; return TRUE;
} }
int32 field::check_trigger_effect(const chain& ch) const {
effect* peffect = ch.triggering_effect;
card* phandler = peffect->get_handler();
if((peffect->type & EFFECT_TYPE_FIELD) && !phandler->is_has_relation(ch))
return FALSE;
if(peffect->code == EVENT_FLIP && infos.phase == PHASE_DAMAGE)
return TRUE;
if((phandler->current.location & LOCATION_DECK) && !(ch.flag & CHAIN_DECK_EFFECT))
return FALSE;
if((ch.triggering_location & (LOCATION_DECK | LOCATION_HAND | LOCATION_EXTRA))
&& (ch.triggering_position & POS_FACEDOWN))
return TRUE;
if(!(phandler->current.location & (LOCATION_DECK | LOCATION_HAND | LOCATION_EXTRA))
|| phandler->is_position(POS_FACEUP))
return TRUE;
return FALSE;
}
int32 field::check_spself_from_hand_trigger(const chain& ch) const { int32 field::check_spself_from_hand_trigger(const chain& ch) const {
effect* peffect = ch.triggering_effect; effect* peffect = ch.triggering_effect;
uint8 tp = ch.triggering_player; uint8 tp = ch.triggering_player;
......
...@@ -219,6 +219,7 @@ struct processor { ...@@ -219,6 +219,7 @@ struct processor {
card_set unique_destroy_set; card_set unique_destroy_set;
card_set self_destroy_set; card_set self_destroy_set;
card_set self_tograve_set; card_set self_tograve_set;
card_set trap_monster_adjust_set[2];
card_set release_cards; card_set release_cards;
card_set release_cards_ex; card_set release_cards_ex;
card_set release_cards_ex_oneof; card_set release_cards_ex_oneof;
...@@ -240,7 +241,6 @@ struct processor { ...@@ -240,7 +241,6 @@ struct processor {
std::unordered_map<uint32, uint32> effect_count_code; std::unordered_map<uint32, uint32> effect_count_code;
std::unordered_map<uint32, uint32> effect_count_code_duel; std::unordered_map<uint32, uint32> effect_count_code_duel;
std::unordered_map<uint32, uint32> spsummon_once_map[2]; std::unordered_map<uint32, uint32> spsummon_once_map[2];
std::unordered_map<uint32, uint32> spsummon_once_map_rst[2];
std::multimap<int32, card*, std::greater<int32>> xmaterial_lst; std::multimap<int32, card*, std::greater<int32>> xmaterial_lst;
ptr temp_var[4]; ptr temp_var[4];
uint32 global_flag; uint32 global_flag;
...@@ -484,9 +484,7 @@ public: ...@@ -484,9 +484,7 @@ public:
int32 get_cteffect(effect* peffect, int32 playerid, int32 store); int32 get_cteffect(effect* peffect, int32 playerid, int32 store);
int32 get_cteffect_evt(effect* feffect, int32 playerid, const tevent& e, int32 store); int32 get_cteffect_evt(effect* feffect, int32 playerid, const tevent& e, int32 store);
int32 check_cteffect_hint(effect* peffect, uint8 playerid); int32 check_cteffect_hint(effect* peffect, uint8 playerid);
int32 check_deck_effect(chain& ch) const;
int32 check_hand_trigger(chain& ch); int32 check_hand_trigger(chain& ch);
int32 check_trigger_effect(const chain& ch) const;
int32 check_spself_from_hand_trigger(const chain& ch) const; int32 check_spself_from_hand_trigger(const chain& ch) const;
int32 is_able_to_enter_bp(); int32 is_able_to_enter_bp();
...@@ -565,6 +563,7 @@ public: ...@@ -565,6 +563,7 @@ public:
int32 swap_control(uint16 step, effect* reason_effect, uint8 reason_player, group* targets1, group* targets2, uint16 reset_phase, uint8 reset_count); int32 swap_control(uint16 step, effect* reason_effect, uint8 reason_player, group* targets1, group* targets2, uint16 reset_phase, uint8 reset_count);
int32 control_adjust(uint16 step); int32 control_adjust(uint16 step);
int32 self_destroy(uint16 step, card* ucard, int32 p); int32 self_destroy(uint16 step, card* ucard, int32 p);
int32 trap_monster_adjust(uint16 step);
int32 equip(uint16 step, uint8 equip_player, card* equip_card, card* target, uint32 up, uint32 is_step); int32 equip(uint16 step, uint8 equip_player, card* equip_card, card* target, uint32 up, uint32 is_step);
int32 draw(uint16 step, effect* reason_effect, uint32 reason, uint8 reason_player, uint8 playerid, uint32 count); int32 draw(uint16 step, effect* reason_effect, uint32 reason, uint8 reason_player, uint8 playerid, uint32 count);
int32 damage(uint16 step, effect* reason_effect, uint32 reason, uint8 reason_player, card* reason_card, uint8 playerid, uint32 amount, uint32 is_step); int32 damage(uint16 step, effect* reason_effect, uint32 reason, uint8 reason_player, card* reason_card, uint8 playerid, uint32 amount, uint32 is_step);
...@@ -626,7 +625,7 @@ public: ...@@ -626,7 +625,7 @@ public:
#define CHAIN_CONTINUOUS_CARD 0x08 #define CHAIN_CONTINUOUS_CARD 0x08
#define CHAIN_ACTIVATING 0x10 #define CHAIN_ACTIVATING 0x10
#define CHAIN_HAND_TRIGGER 0x20 #define CHAIN_HAND_TRIGGER 0x20
#define CHAIN_DECK_EFFECT 0x40 //#define CHAIN_DECK_EFFECT 0x40
#define CHAININFO_CHAIN_COUNT 0x01 #define CHAININFO_CHAIN_COUNT 0x01
#define CHAININFO_TRIGGERING_EFFECT 0x02 #define CHAININFO_TRIGGERING_EFFECT 0x02
#define CHAININFO_TRIGGERING_PLAYER 0x04 #define CHAININFO_TRIGGERING_PLAYER 0x04
...@@ -756,6 +755,7 @@ public: ...@@ -756,6 +755,7 @@ public:
#define PROCESSOR_SWAP_CONTROL 75 #define PROCESSOR_SWAP_CONTROL 75
#define PROCESSOR_CONTROL_ADJUST 76 #define PROCESSOR_CONTROL_ADJUST 76
#define PROCESSOR_SELF_DESTROY 77 #define PROCESSOR_SELF_DESTROY 77
#define PROCESSOR_TRAP_MONSTER_ADJUST 78
#define PROCESSOR_PAY_LPCOST 80 #define PROCESSOR_PAY_LPCOST 80
#define PROCESSOR_REMOVE_COUNTER 81 #define PROCESSOR_REMOVE_COUNTER 81
#define PROCESSOR_ATTACK_DISABLE 82 #define PROCESSOR_ATTACK_DISABLE 82
......
...@@ -4104,7 +4104,7 @@ int32 scriptlib::duel_is_chain_negatable(lua_State * L) { ...@@ -4104,7 +4104,7 @@ int32 scriptlib::duel_is_chain_negatable(lua_State * L) {
chain* ch = pduel->game_field->get_chain(chaincount); chain* ch = pduel->game_field->get_chain(chaincount);
if(!ch) if(!ch)
return 0; return 0;
if(ch->flag & CHAIN_DECK_EFFECT) if(ch->triggering_location == LOCATION_DECK)
lua_pushboolean(L, 0); lua_pushboolean(L, 0);
else else
lua_pushboolean(L, 1); lua_pushboolean(L, 1);
...@@ -4121,7 +4121,7 @@ int32 scriptlib::duel_is_chain_disablable(lua_State * L) { ...@@ -4121,7 +4121,7 @@ int32 scriptlib::duel_is_chain_disablable(lua_State * L) {
chain* ch = pduel->game_field->get_chain(chaincount); chain* ch = pduel->game_field->get_chain(chaincount);
if(!ch) if(!ch)
return 0; return 0;
if(ch->flag & CHAIN_DECK_EFFECT) if(ch->triggering_location == LOCATION_DECK)
lua_pushboolean(L, 0); lua_pushboolean(L, 0);
else else
lua_pushboolean(L, 1); lua_pushboolean(L, 1);
......
This diff is collapsed.
...@@ -490,6 +490,13 @@ int32 field::process() { ...@@ -490,6 +490,13 @@ int32 field::process() {
it->step++; it->step++;
return pduel->bufferlen; return pduel->bufferlen;
} }
case PROCESSOR_TRAP_MONSTER_ADJUST: {
if (trap_monster_adjust(it->step))
core.units.pop_front();
else
it->step++;
return pduel->bufferlen;
}
case PROCESSOR_PAY_LPCOST: { case PROCESSOR_PAY_LPCOST: {
if (pay_lp_cost(it->step, it->arg1, it->arg2)) if (pay_lp_cost(it->step, it->arg1, it->arg2))
core.units.pop_front(); core.units.pop_front();
...@@ -1306,8 +1313,7 @@ int32 field::process_point_event(int16 step, int32 skip_trigger, int32 skip_free ...@@ -1306,8 +1313,7 @@ int32 field::process_point_event(int16 step, int32 skip_trigger, int32 skip_free
if(phandler->is_has_relation(*clit)) //work around: position and control should be refreshed before raising event if(phandler->is_has_relation(*clit)) //work around: position and control should be refreshed before raising event
clit->set_triggering_state(phandler); clit->set_triggering_state(phandler);
uint8 tp = clit->triggering_player; uint8 tp = clit->triggering_player;
if(check_deck_effect(*clit) && check_trigger_effect(*clit) if(phandler->is_has_relation(*clit) && peffect->is_chainable(tp) && peffect->is_activateable(tp, clit->evt, TRUE)) {
&& peffect->is_chainable(tp) && peffect->is_activateable(tp, clit->evt, TRUE)) {
if(tp == core.current_player) if(tp == core.current_player)
core.select_chains.push_back(*clit); core.select_chains.push_back(*clit);
} else { } else {
...@@ -1364,7 +1370,7 @@ int32 field::process_point_event(int16 step, int32 skip_trigger, int32 skip_free ...@@ -1364,7 +1370,7 @@ int32 field::process_point_event(int16 step, int32 skip_trigger, int32 skip_free
clit->set_triggering_state(phandler); clit->set_triggering_state(phandler);
} }
uint8 tp = clit->triggering_player; uint8 tp = clit->triggering_player;
if(check_hand_trigger(*clit) && check_deck_effect(*clit) && check_trigger_effect(*clit) if(check_hand_trigger(*clit) && phandler->is_has_relation(*clit)
&& peffect->is_chainable(tp) && peffect->is_activateable(tp, clit->evt, TRUE) && peffect->is_chainable(tp) && peffect->is_activateable(tp, clit->evt, TRUE)
&& check_spself_from_hand_trigger(*clit)) { && check_spself_from_hand_trigger(*clit)) {
if(tp == core.current_player) if(tp == core.current_player)
...@@ -3643,7 +3649,6 @@ int32 field::process_turn(uint16 step, uint8 turn_player) { ...@@ -3643,7 +3649,6 @@ int32 field::process_turn(uint16 step, uint8 turn_player) {
core.summon_count[p] = 0; core.summon_count[p] = 0;
core.extra_summon[p] = 0; core.extra_summon[p] = 0;
core.spsummon_once_map[p].clear(); core.spsummon_once_map[p].clear();
core.spsummon_once_map_rst[p].clear();
} }
core.spsummon_rst = false; core.spsummon_rst = false;
for(auto& peffect : effects.rechargeable) for(auto& peffect : effects.rechargeable)
...@@ -4156,38 +4161,7 @@ int32 field::add_chain(uint16 step) { ...@@ -4156,38 +4161,7 @@ int32 field::add_chain(uint16 step) {
set_spsummon_counter(clit.triggering_player, true, true); set_spsummon_counter(clit.triggering_player, true, true);
if(clit.opinfos[0x200].op_player == PLAYER_ALL) if(clit.opinfos[0x200].op_player == PLAYER_ALL)
set_spsummon_counter(1 - clit.triggering_player, true, true); set_spsummon_counter(1 - clit.triggering_player, true, true);
if(core.global_flag & GLOBALFLAG_SPSUMMON_ONCE) {
auto& optarget = clit.opinfos[0x200];
if(optarget.op_cards) {
if(optarget.op_player == PLAYER_ALL) {
auto opit = optarget.op_cards->container.begin();
uint32 sumplayer = optarget.op_param;
if((*opit)->spsummon_code) {
core.spsummon_once_map[sumplayer][(*opit)->spsummon_code]++;
core.spsummon_once_map_rst[sumplayer][(*opit)->spsummon_code]++;
}
++opit;
if((*opit)->spsummon_code) {
core.spsummon_once_map[1 - sumplayer][(*opit)->spsummon_code]++;
core.spsummon_once_map_rst[1 - sumplayer][(*opit)->spsummon_code]++;
} }
} else {
uint32 sumplayer = clit.triggering_player;
// genarally setting op_player is unnecessary when the effect targets cards
// in the case of CATEGORY_SPECIAL_SUMMON(with EFFECT_FLAG_CARD_TARGET), op_player=0x10
// indecates that it is the opponent that special summons the target monsters
if(peffect->is_flag(EFFECT_FLAG_CARD_TARGET) && optarget.op_player == 0x10)
sumplayer = 1 - sumplayer;
for(auto& pcard : optarget.op_cards->container) {
if(pcard->spsummon_code) {
core.spsummon_once_map[sumplayer][pcard->spsummon_code]++;
core.spsummon_once_map_rst[sumplayer][pcard->spsummon_code]++;
}
}
}
}
}
}
pduel->write_buffer8(MSG_CHAINED); pduel->write_buffer8(MSG_CHAINED);
pduel->write_buffer8(clit.chain_count); pduel->write_buffer8(clit.chain_count);
raise_event(phandler, EVENT_CHAINING, peffect, 0, clit.triggering_player, clit.triggering_player, clit.chain_count); raise_event(phandler, EVENT_CHAINING, peffect, 0, clit.triggering_player, clit.triggering_player, clit.chain_count);
...@@ -4308,13 +4282,6 @@ int32 field::solve_chain(uint16 step, uint32 chainend_arg1, uint32 chainend_arg2 ...@@ -4308,13 +4282,6 @@ int32 field::solve_chain(uint16 step, uint32 chainend_arg1, uint32 chainend_arg2
if(core.spsummon_rst) { if(core.spsummon_rst) {
set_spsummon_counter(0, false, true); set_spsummon_counter(0, false, true);
set_spsummon_counter(1, false, true); set_spsummon_counter(1, false, true);
for(int plr = 0; plr < 2; ++plr) {
for(auto& iter : core.spsummon_once_map[plr]) {
auto spcode = iter.first;
core.spsummon_once_map[plr][spcode] -= core.spsummon_once_map_rst[plr][spcode];
core.spsummon_once_map_rst[plr][spcode] = 0;
}
}
core.spsummon_rst = false; core.spsummon_rst = false;
} }
pduel->write_buffer8(MSG_CHAIN_SOLVING); pduel->write_buffer8(MSG_CHAIN_SOLVING);
...@@ -4408,37 +4375,6 @@ int32 field::solve_chain(uint16 step, uint32 chainend_arg1, uint32 chainend_arg2 ...@@ -4408,37 +4375,6 @@ int32 field::solve_chain(uint16 step, uint32 chainend_arg1, uint32 chainend_arg2
set_spsummon_counter(cait->triggering_player); set_spsummon_counter(cait->triggering_player);
if(cait->opinfos[0x200].op_player == PLAYER_ALL && core.spsummon_state_count_tmp[1 - cait->triggering_player] == core.spsummon_state_count[1 - cait->triggering_player]) if(cait->opinfos[0x200].op_player == PLAYER_ALL && core.spsummon_state_count_tmp[1 - cait->triggering_player] == core.spsummon_state_count[1 - cait->triggering_player])
set_spsummon_counter(1 - cait->triggering_player); set_spsummon_counter(1 - cait->triggering_player);
//sometimes it may add twice, only works for once per turn
auto& optarget = cait->opinfos[0x200];
if(optarget.op_cards) {
if(optarget.op_player == PLAYER_ALL) {
uint32 sumplayer = optarget.op_param;
if(core.global_flag & GLOBALFLAG_SPSUMMON_ONCE) {
auto opit = optarget.op_cards->container.begin();
if((*opit)->spsummon_code)
core.spsummon_once_map[sumplayer][(*opit)->spsummon_code]++;
++opit;
if((*opit)->spsummon_code)
core.spsummon_once_map[1 - sumplayer][(*opit)->spsummon_code]++;
}
auto opit = optarget.op_cards->container.begin();
check_card_counter(*opit, 3, sumplayer);
++opit;
check_card_counter(*opit, 3, 1 - sumplayer);
} else {
uint32 sumplayer = cait->triggering_player;
// genarally setting op_player is unnecessary when the effect targets cards
// in the case of CATEGORY_SPECIAL_SUMMON(with EFFECT_FLAG_CARD_TARGET), op_player=0x10
// indecates that it is the opponent that special summons the target monsters
if(cait->triggering_effect->is_flag(EFFECT_FLAG_CARD_TARGET) && optarget.op_player == 0x10)
sumplayer = 1 - sumplayer;
for(auto& ptarget : optarget.op_cards->container) {
if((core.global_flag & GLOBALFLAG_SPSUMMON_ONCE) && ptarget->spsummon_code)
core.spsummon_once_map[sumplayer][ptarget->spsummon_code]++;
check_card_counter(ptarget, 3, sumplayer);
}
}
}
} }
} }
core.spsummon_state_count_tmp[0] = 0; core.spsummon_state_count_tmp[0] = 0;
...@@ -4839,18 +4775,19 @@ int32 field::adjust_step(uint16 step) { ...@@ -4839,18 +4775,19 @@ int32 field::adjust_step(uint16 step) {
} }
case 3: { case 3: {
//trap monster //trap monster
uint8 tp = infos.turn_player; core.trap_monster_adjust_set[0].clear();
core.trap_monster_adjust_set[1].clear();
for(uint8 p = 0; p < 2; ++p) { for(uint8 p = 0; p < 2; ++p) {
for(auto& pcard : player[tp].list_mzone) { for(auto& pcard : player[p].list_mzone) {
if(!pcard) continue; if(!pcard) continue;
if((pcard->get_type() & TYPE_TRAPMONSTER) && pcard->is_affected_by_effect(EFFECT_DISABLE_TRAPMONSTER)) { if((pcard->get_type() & TYPE_TRAPMONSTER) && pcard->is_affected_by_effect(EFFECT_DISABLE_TRAPMONSTER)) {
pcard->reset(RESET_TURN_SET, RESET_EVENT); core.trap_monster_adjust_set[p].insert(pcard);
refresh_location_info_instant();
move_to_field(pcard, tp, tp, LOCATION_SZONE, pcard->current.position, FALSE, 2);
core.re_adjust = TRUE;
} }
} }
tp = 1 - tp; }
if(core.trap_monster_adjust_set[0].size() || core.trap_monster_adjust_set[1].size()) {
core.re_adjust = TRUE;
add_process(PROCESSOR_TRAP_MONSTER_ADJUST, 0, 0, 0, 0, 0);
} }
return FALSE; return FALSE;
} }
......
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