def parser(situation: model.Situation) -> t_world: log = _logger.getChild("parser") world = t_world( fields_={}, switches=situation.switches) log.info("parser()") log.debug("IN situation.orders: %s", dip_eval.LogList(situation.orders, prefix="\n-o ")) # umkremepeln: wir betrachten Felder, die sich gegenseitig angreifen. for o in situation.orders: if world.get_field(o.current): # schon drin raise LookupError(f"fieldname {o.current} twice in current.") field = t_field_from_order(o) # add world.set_field(field) # the world representation needs empty explicit empty fields for destinations. all_currents = { f.name for f in world.get_fields() } all_dests = { f.dest for f in world.get_fields() } log.debug("adding needed empty destination fields: %s", all_dests - all_currents) for dest in all_dests - all_currents: world.set_field(t_field_empty(dest)) # change nmoves to cmoves field : t_field for field, dest_field in world.get_fields_dests(lambda f: f.order in { t_order.convoy } ): if field.order in { t_order.nmove }: log.debug("- changing nmove to cmove for field:%s because of dest:%s", field, dest_field) field.order = t_order.cmove field.add_event("$cmove") # result log.debug("OUT world.fields: %s", dip_eval.LogList(world.get_fields())) return world
def writer(world: t_world) -> model.ConflictResolution: log = _logger.getChild("writer") orders: List[model.OrderResult] = [] f: t_field log.info("writer()") log.debug("IN world.fields: %s", dip_eval.LogList(world.get_fields())) # moves for f in world.get_fields(): if f.player == NO_PLAYER: continue # empty fields that were just destinations order = order_from_t_order(f.order) orr = model.OrderResult( nation=f.player, utype=f.original_order.utype if f.original_order else '?', current=f.name, order=order, dest=f.dest, # TODO or xref? or original.dest? succeeds=False if not f.succeeds else None, dislodged=True if f.dislodged else None, original=f.original_order ) orders.append(orr) # figure out pattfields. TODO: alpha efields = { f.name for f in world.get_fields(lambda f: f.player == NO_PLAYER) } ufields = { f.dest for f in world.get_fields(lambda f: f.order in {t_order.umove}) } sfields = { f.dest for f in world.get_fields(lambda f: f.order in {t_order.nmove, t_order.cmove}) } hfields = { f.name for f in world.get_fields(lambda f: f.order in {t_order.hsupport, t_order.msupport, t_order.none }) } # .. (all empty fields and fields with blocked moved) minus (destination of moves) minus (hold fields ignoring empty fields) pattfields = (efields | ufields) - sfields - (hfields - efields) # log.debug("OUT conflict_resolution.orders: %s, ", dip_eval.LogList(orders, prefix="\n-r ")) log.debug("OUT conflict_resolution.pattfields: %s, ", pattfields) return model.ConflictResolution(orders=orders, pattfields=pattfields)
def k4_evaluation(world: t_world): log = _logger.getChild("k4_evaluation") log.info("k4_evaluation") # prepare # - aliases for brevity hsupport, msupport, cmove, nmove, umove = t_order.hsupport, t_order.msupport, t_order.cmove, t_order.nmove, t_order.umove # # {mark k4 felds} ifield: t_field dest_field: t_field for ifield, dest_field in world.get_fields_dests( lambda f: f.order in {cmove, nmove, umove}): if dest_field.fcategory == 0: dest_field.fcategory = 4 dest_field.add_event('$k4f') # # {mark k4 moves and supports} for ifield, dest_field in world.get_fields_dests( lambda f: f.order in {hsupport, msupport, cmove, nmove}): if dest_field.fcategory == 4: ifield.category = 4 ifield.add_event('$k4c') eval_common.cut_supports(world, category=4, relevant_moves={cmove, nmove, umove}) eval_common.count_supporters(world, category=4) # # units block each other in a chain. # - guard protects against accidental forever-loop, which should not happen; # assuming there will never be chains of blocking units longer then this. guard = 1000 # programming error guard changed_flag: bool = True while changed_flag: # {evaluate conflicts} for ifield in world.get_fields(lambda f: f.fcategory == 4): log.debug(". resolve conflict at field: %s", ifield.__log__()) eval_common.resolve_conflict_at_field(world, ifield) # {mark k4 moves which fail now, but succeeded in the previous iteration} changed_flag = False for ifield in world.get_fields(lambda f: f.category == 4 and f.order in {cmove, nmove} and not f.succeeds): ifield.order = t_order.none ifield.add_event("$chain4") changed_flag = True guard -= 1 if guard <= 0: raise OverflowError( "programming error (likely) or blocking-chain too long (unlikely)" ) log.debug("_ evaluate conflicts loop. changed:%s. fields: %s", changed_flag, dip_eval.LogList(world.get_fields())) # log.debug("DONE k4. fields: %s", dip_eval.LogList(world.get_fields())) return
def k1_evaluation(world: t_world): log = _logger.getChild("k1_evaluation") log.info("k1_evaluation") # prepare # - aliases for brevity hsupport, msupport, cmove, nmove, umove, convoy = t_order.hsupport, t_order.msupport, t_order.cmove, t_order.nmove, t_order.umove, t_order.convoy # # {mark k1 fields} ifield : t_field dest_field : t_field for ifield in world.get_fields(lambda f: f.order in { convoy }): ifield.fcategory = 1 ifield.add_event('$k1f') # # {mark k1 moves and supports} for ifield, dest_field in world.get_fields_dests(lambda f: f.order in { hsupport, msupport, nmove }): if dest_field.fcategory == 1: ifield.category = 1 ifield.add_event('$k1c') log.debug("k1 moves and support marks. fields: %s", dip_eval.LogList(world.get_fields(lambda f: f.category == 1))) eval_common.cut_supports(world, category=1, relevant_moves={nmove}) eval_common.count_supporters(world, category=1) log.debug("k1 cuts and supports. fields: %s", dip_eval.LogList(world.get_fields(lambda f: f.category == 1))) # # {evaluate conflicts} for ifield in world.get_fields(lambda f: f.category==1): eval_common.resolve_conflict_at_field(world, ifield) eval_common.change_moves_to_umoves(world, category=1) # # {evaluate dislodgements of convoyers} for ifield, dest_field in world.get_fields_dests(lambda f: f.category==1 and f.order in {nmove}): dest_field.order = t_order.none dest_field.add_event("$cdsl") log.debug("k1 blocked dislodged convoyer field:%s because of %s", dest_field, ifield) # # {check convoy routes} for ifield in world.get_fields(lambda f: f.order in {cmove}): my_convoyers = { jfield.name for jfield in world.get_fields() if jfield.order in {convoy} and jfield.xref == ifield.name } if not convoy_route_valid(world=world, field=ifield, convoyer_names=my_convoyers): ifield.order = t_order.none ifield.add_event("$criv") # convoy route invalid log.debug("k1 invalid convoy route for field:%s via %s", ifield, my_convoyers) # log.debug("DONE k1. fields: %s", dip_eval.LogList(world.get_fields())) return
def k2_evaluation(world: t_world): log = _logger.getChild("k2_evaluation") log.info("k2_evaluation") # prepare # - aliases for brevity hsupport, msupport, cmove, nmove, umove = t_order.hsupport, t_order.msupport, t_order.cmove, t_order.nmove, t_order.umove # - k2_relevant_moves k2_relevant_moves = { nmove } if world.switches.convoy_cuts: k2_relevant_moves.add(cmove) # # {mark k2 fields} ifield : t_field dest_field : t_field for ifield, dest_field in world.get_fields_dests(lambda f: f.order in { msupport }): if dest_field.order in k2_relevant_moves and dest_field.dest==ifield.name: ifield.fcategory = 2 ifield.add_event('$k2f') # .. {it may seem to be wrong that no check is included, whether # both units belong to different players, but this case does no harm} # # {mark k2 moves and supports} for ifield, dest_field in world.get_fields_dests(lambda f: f.order in { hsupport, msupport, cmove, nmove }): if dest_field.fcategory == 2: ifield.category = 2 ifield.add_event('$k2c') log.debug("k2 moves and support marks. fields: %s", dip_eval.LogList(world.get_fields(lambda f: f.category == 2))) eval_common.cut_supports(world, category=2, relevant_moves={cmove, nmove, umove}) eval_common.count_supporters(world, category=2) log.debug("k2 cuts and supports. fields: %s", dip_eval.LogList(world.get_fields(lambda f: f.category == 2))) # # {evaluate conflicts} for ifield in world.get_fields(lambda f: f.fcategory==2): log.debug("k2 resolve_conflict_at_field: %s", ifield) eval_common.resolve_conflict_at_field(world, ifield) # # {change unsuccessfull critical k2 moves to nops} for ifield, dest_field in world.get_fields_dests(lambda f: f.category==2 and f.order in k2_relevant_moves and not f.succeeds): if dest_field.order in {msupport} and dest_field.dest==ifield.name: ifield.order = t_order.none ifield.add_event("$ck2n") eval_common.change_moves_to_umoves(world, category=2) # log.debug("DONE k2. fields: %s", dip_eval.LogList(world.get_fields())) return
def k0_evaluation(world: t_world): log = _logger.getChild("k0_evaluation") log.info("k0_evaluation") # # {count the supports for fields which aren't attacked (920112)} eval_common.cut_supports(world, 0, {t_order.cmove, t_order.nmove, t_order.umove}) eval_common.count_supporters(world, 0) # log.debug("DONE k0. fields: %s", dip_eval.LogList(world.get_fields())) return
def k3_evaluation(world: t_world): log = _logger.getChild("k3_evaluation") log.info("k3_evaluation") # prepare # - aliases for brevity hsupport, msupport, cmove, nmove, umove = t_order.hsupport, t_order.msupport, t_order.cmove, t_order.nmove, t_order.umove # - rule interpretation switches _ri97 = world.switches.rule_interpretation_IX_7 # # {mark k3 fields} ifield: t_field dest_field: t_field for ifield, dest_field in world.get_fields_dests( lambda f: f.order in {nmove}): if dest_field.order in {nmove} and dest_field.dest == ifield.name: ifield.fcategory = 3 ifield.add_event('$k3f') log.debug("k3. conflict at border identified of fields:%s and:%s", ifield, dest_field) # # {mark k3 moves and supports} for ifield, dest_field in world.get_fields_dests( lambda f: f.order in {hsupport, msupport, cmove, nmove}): if dest_field.fcategory == 3: ifield.category = 3 ifield.add_event('$k3c') eval_common.cut_supports(world, category=3, relevant_moves={cmove, nmove, umove}) eval_common.count_supporters(world, category=3) # # {evaluate conflicts pairwise} for ifield, dest_field in world.get_fields_dests( lambda f: f.category == 3): if ifield.name < dest_field.name: eval_common.resolve_conflict_at_border(world, ifield, dest_field) # {choose n to be not the looser of the border conflict} n: t_field m: t_field if ifield.succeeds: n, m = ifield, dest_field else: m, n = ifield, dest_field if n.succeeds: # {does n not only win at the order but also at the target field?} m.add_event("$nwin") eval_common.resolve_conflict_at_field(world, m) if n.succeeds or _ri97 > 0: # {the weaker move has no effect} m.add_event("$mlooseA") m.order = t_order.none eval_common.resolve_conflict_at_field(world, n) else: # {the weaker move will not succeed} m.add_event("$mlooseB") eval_common.resolve_conflict_at_field(world, n) m.succeeds = False else: # {draw at border} m.add_event("$bdraw") if _ri97 == 2: # {the opposing moves have no effect} m.add_event("$bdraw2m") n.add_event("$bdraw2n") m.order = t_order.none eval_common.resolve_conflict_at_field(world, n) n.order = t_order.none eval_common.resolve_conflict_at_field(world, m) else: # {the opposing moves will not succeed} m.add_event("$bdrawXm") n.add_event("$bdrawXn") eval_common.resolve_conflict_at_field(world, n) m.succeeds = False eval_common.resolve_conflict_at_field(world, m) n.succeeds = False pass # end if _ri97 == 2 else pass # end if n.succeeds else pass # end if ifield.name < ifield.dest # eval_common.change_moves_to_umoves(world, category=3) # log.debug("DONE k3. fields: %s", dip_eval.LogList(world.get_fields())) return