[Magic Brew] Further Ideas
Towards theoretical perfection ...
Current Issues
Main issues:
-
Incomplete knowledge base structure
- Manual filter definition (creation + new set release updates)
- Manual filter clustering (ad hoc)
- Manual glossary selection (ad hoc)
- Manual glossary/filter linkage (ad hoc)
- Implementation limits (HTTrack/Gatherer search query length)
-
Incomplete knowledge base data
- Expressive power limits (Oracle card text pattern matching)
- Manual regression test precision limits (false positives/negatives inspection)
-
Untimely knowledge base generation
- Manual knowledge base structure (creation + new set release updates)
- Manual knowledge base data (false positives/negatives inspection)
- Automated knowledge base generation (excessive web crawling)
Ultimate Solution
Cards integration within the knowledge base itself, i.e. bidirectional linkage between search filter definitions and cards, instead of unidirectional linkage from search filter definitions to Gatherer search filter results to cards.
This would require translating each existing Gatherer card (and in particular its Oracle card text) into a more fundamental representation. In analogy to e.g. Java computer programs, or more precisely the equivalent Java Byte Code instructions, being executable on a Java Virtual Machine, the Magic: The Gathering representation layer should consist of MGL (i.e. 'Magic Game Language') card declarations, or more precisely the equivalent MGC (i.e. 'Magic Game Code') instructions, directly executable on a MVM (i.e. 'Magic Virtual Machine') = Comprehensive Rules implementation. Filter definitions would then be expressed in MQL (i.e. 'Magic Query Language'), i.e. advanced 'tagging' (e.g. by means of Scryfall Tagger).
Let it be clear that all of this goes way beyond the current pragmatic Magic Brew approach.
Ultimate solution benefits:
-
Knowledge base structure completeness
- (semi-)automated filter definition/clustering
- automated glossary/filter linkage
- no implementation limits (within external system/tool)
-
Knowledge base data completeness
- automated filter/card linkage
- no manual regression testing (false positives/negatives inspection)
- no implementation limits (within external system/tool)
-
Knowledge base generation timeliness
- no extensive web crawling (within external system/tool)
- no new filter/new card linkage testing
- no manual regression testing (false positives/negatives inspection)
-
Derived (A.I.) applications potential
- Comprehensive Rules training (examples, simulations, puzzles)
- deck construction/selection
- draft/play advice
Ultimate solution requirement:
-
Comprehensive Rules + Oracle card text interpretation/implementation correctness
As the only remaining (complex) manual work upon each new set release, i.e. iterative new mechanics/cards 'translation', it all comes down to this ...
Tech Hint
To intuitively illustrate above mentioned MGL, MGC, MVM, and MQL concepts, please find the simplified triggered ability example 'When Cyclopean Mummy dies, exile it.' in hypothetical pseudo-code below. This pseudo-code by no means provides any indication of any actual solution realization. The [*1*] .. [*7*] markers highlight the main points in the event-driven execution flow (i.e. from creature death to exile).
MQL_FILTER sacrifice_or_die_or_destroy { LEAVE_BATTLEFIELD + ENTER_GRAVEYARD } MGL_ABILITY abi = { ability:TRIGGERED_ABILITY . condition:ZONE-CHANGE . object == abi . source ability:TRIGGERED_ABILITY . condition:ZONE-CHANGE . event#1 == LEAVE_BATTLEFIELD ability:TRIGGERED_ABILITY . condition:ZONE-CHANGE . event#2:ENTER_GRAVEYARD . owner == abi . source . owner ability:TRIGGERED_ABILITY . effect:ZONE-CHANGE . object == abi . source ability:TRIGGERED_ABILITY . effect:ZONE-CHANGE . event#1:LEAVE_GRAVEYARD . owner == abi . source . owner ability:TRIGGERED_ABILITY . effect:ZONE-CHANGE . event#2 == ENTER_EXILE } MGC_INSTRUCTIONS generic__creature_dies (object:o1) { PLAYER p_1 = get_owner (o_1); ZONE z_1 = get_zone (zone-type:TYPE_GRAVEYARD, owner:p_1); EVENT e_1 == create_event (event-type:TYPE_OBJECT_LIFECYCLE, subevent-type:LEAVE_BATTLEFIELD, object:o_1); throw_event (event:e_1); [*2*] OBJECT o_2 = create_object (from-object:o_1, owner:p_1); destroy_object (object:o_1); EVENT e_2 == create_event (event-type:TYPE_OBJECT_LIFECYCLE, subevent-type:ENTER_GRAVEYARD, zone:z_1, object:o_2); throw_event (event:e_2); [*3*] } MGC_INSTRUCTIONS compiled__abi_effect (compiled__abi_ability:a_11) { OBJECT o_11 = get_source (ability:a_11); PLAYER p_11 = get_owner (o_11); ZONE z_11 = get_zone (zone-type:TYPE_GRAVEYARD, owner:p_11); EVENT e_11 == create_event (event-type:TYPE_OBJECT_LIFECYCLE, subevent-type:LEAVE_GRAVEYARD, zone:z_11, object:o_11); throw_game_event (event:e_11); [*6*] OBJECT o_12 = create_object (from-object:o_11, owner:p_11); destroy_object (object:o_11); EVENT e_12 == create_event (event-type:TYPE_OBJECT_LIFECYCLE, subevent-type:ENTER_EXILE, object:o_12); throw_game_event (event:e_12); [*7*] } MVM_MODULE event_handler loop (forever) { wait_until_next_game_event_is_thrown(); EVENT e = catch_next_game_event(); test (e.event-type + subevent-type) { ... if (TYPE_STATE_BASED_ACTION + DESTROY_CREATURE) then { OBJECT c = get_dying_creature (event:e); INSTRUCTIONS is = load_instructions_for___generic__creature_dies (); execute_effect (instructions:is, data:c); [*1*] } ... if (TYPE_OBJECT_LIFECYCLE + ENTER_GRAVEYARD) then { OBJECTS ts = find_all_applicable_triggers_for_event (event:e); loop (OBJECT t IN ts) { push_onto_stack (object:t); [*4*] } } ... } } MVM_MODULE stack_resolver loop (forever) { wait_until_top_of_stack_is_ready_to_resolve(); OBJECT t = pop_top_from_stack(); INSTRUCTIONS is = load_instructions_for___compiled__effect (object:t); execute_effect (instructions:is, data:t); [*5*] }
back to: Card Pools