Esempio n. 1
0
File: phase.go Progetto: arlm/godip
func (self *phase) PostProcess(s dip.State) (err error) {
	if self.typ == cla.Retreat {
		for prov, _ := range s.Dislodgeds() {
			s.RemoveDislodged(prov)
			s.SetResolution(prov, cla.ErrForcedDisband)
		}
		s.ClearDislodgers()
		s.ClearBounces()
		if self.season == cla.Fall {
			s.Find(func(p dip.Province, o dip.Order, u *dip.Unit) bool {
				if u != nil {
					if s.Graph().SC(p) != nil {
						s.SetSC(p.Super(), u.Nation)
					}
				}
				return false
			})
		}
	} else if self.typ == cla.Adjustment {
		for _, nationality := range cla.Nations {
			_, _, balance := cla.AdjustmentStatus(s, nationality)
			if balance < 0 {
				var su []dip.Province
				if su, err = self.sortedUnits(s, nationality); err != nil {
					return
				}
				su = su[:-balance]
				for _, prov := range su {
					dip.Logf("Removing %v due to forced disband", prov)
					s.RemoveUnit(prov)
					s.SetResolution(prov, cla.ErrForcedDisband)
				}
			}
		}
	} else if self.typ == cla.Movement {
		for prov, unit := range s.Dislodgeds() {
			hasRetreat := false
			for edge, _ := range s.Graph().Edges(prov) {
				if _, _, ok := s.Unit(edge); !ok && !s.Bounce(prov, edge) {
					if cla.HasEdge(s, unit.Type, prov, edge) {
						dip.Logf("%v can retreat to %v", prov, edge)
						hasRetreat = true
						break
					}
				}
			}
			if !hasRetreat {
				s.RemoveDislodged(prov)
				dip.Logf("Removing %v since it has no retreat", prov)
			}
		}
	}
	return
}
Esempio n. 2
0
func (self *resolver) adjudicate(prov common.Province) (err error) {
	common.Logf("Adj(%v)", prov)
	common.Indent("  ")
	err = self.State.orders[prov].Adjudicate(self)
	common.DeIndent()
	if err == nil {
		common.Logf("%v: Success", prov)
	} else {
		common.Logf("%v: Failure: %v", prov, err)
	}
	return
}
Esempio n. 3
0
File: state.go Progetto: arlm/godip
func (self *movement) execute(s *State) (err error) {
	if dislodged, prov, ok := s.Unit(self.dst); ok {
		s.RemoveUnit(prov)
		if err = s.SetDislodged(prov, dislodged); err != nil {
			return
		}
		if self.preventRetreat {
			s.SetDislodger(self.src, prov)
		}
		common.Logf("Dislodged %v from %v", dislodged, self.dst)
	}
	if err = s.SetUnit(self.dst, self.unit); err != nil {
		return
	}
	common.Logf("Dropped %v in %v", self.unit, self.dst)
	return
}
Esempio n. 4
0
File: state.go Progetto: arlm/godip
func (self *movement) prepare(s *State) (err error) {
	var ok bool
	if self.unit, self.src, ok = s.Unit(self.src); !ok {
		err = fmt.Errorf("No unit at %v?", self.src)
		return
	} else {
		s.RemoveUnit(self.src)
	}
	common.Logf("Lifted %v from %v", self.unit, self.src)
	return
}
Esempio n. 5
0
File: move.go Progetto: arlm/godip
func (self *move) adjudicateMovementPhase(r dip.Resolver) error {
	unit, _, _ := r.Unit(self.targets[0])

	convoyed := cla.MustConvoy(r, self.targets[0])
	if convoyed {
		if cla.AnyConvoyPath(r, self.targets[0], self.targets[1], true, nil) == nil {
			return cla.ErrMissingConvoyPath
		}
	}

	if err := self.adjudicateAgainstCompetition(r, nil); err != nil {
		return err
	}

	var forbiddenSupporter *dip.Nation
	// at destination
	if victim, _, hasVictim := r.Unit(self.targets[1]); hasVictim {
		forbiddenSupporter = &victim.Nation
		attackStrength := cla.MoveSupport(r, self.targets[0], self.targets[1], []dip.Nation{victim.Nation}) + 1
		order, prov, _ := r.Order(self.targets[1])
		dip.Logf("'%v' vs '%v': %v", self, order, attackStrength)
		if order.Type() == cla.Move {
			victimConvoyed := cla.MustConvoy(r, order.Targets()[0])
			if !convoyed && !victimConvoyed && order.Targets()[1].Super() == self.targets[0].Super() {
				as := cla.MoveSupport(r, order.Targets()[0], order.Targets()[1], []dip.Nation{unit.Nation}) + 1
				dip.Logf("'%v' vs '%v': %v", order, self, as)
				if victim.Nation == unit.Nation || as >= attackStrength {
					return cla.ErrBounce{self.targets[1]}
				}
			} else {
				dip.Logf("Esc(%v)", order.Targets()[0])
				dip.Indent("  ")
				if err := r.Resolve(prov); err == nil {
					dip.DeIndent()
					dip.Logf("Success")
					forbiddenSupporter = nil
				} else {
					dip.DeIndent()
					dip.Logf("Failure: %v", err)
					if victim.Nation == unit.Nation || 1 >= attackStrength {
						return cla.ErrBounce{self.targets[1]}
					}
				}
			}
		} else {
			hs := cla.HoldSupport(r, self.targets[1]) + 1
			dip.Logf("'%v': %v", order, hs)
			if victim.Nation == unit.Nation || hs >= attackStrength {
				return cla.ErrBounce{self.targets[1]}
			}
		}
	}

	if err := self.adjudicateAgainstCompetition(r, forbiddenSupporter); err != nil {
		return err
	}

	return nil
}
Esempio n. 6
0
File: state.go Progetto: arlm/godip
func (self *State) Retreat(src, dst common.Province) (err error) {
	if unit, prov, ok := self.Dislodged(src); !ok {
		err = fmt.Errorf("No dislodged at %v?", src)
		return
	} else {
		self.RemoveDislodged(prov)
		if err = self.SetUnit(dst, unit); err != nil {
			return
		}
		common.Logf("Moving dislodged %v from %v to %v", unit, src, dst)
	}
	return
}
Esempio n. 7
0
File: move.go Progetto: arlm/godip
func (self *move) adjudicateAgainstCompetition(r dip.Resolver, forbiddenSupporter *dip.Nation) error {
	_, competingOrders, competingUnits := r.Find(func(p dip.Province, o dip.Order, u *dip.Unit) bool {
		return o != nil && u != nil && o.Type() == cla.Move && o.Targets()[0] != self.targets[0] && self.targets[1].Super() == o.Targets()[1].Super()
	})
	for index, competingOrder := range competingOrders {
		var forbiddenSupporters []dip.Nation
		if forbiddenSupporter != nil {
			forbiddenSupporters = append(forbiddenSupporters, *forbiddenSupporter)
		}
		attackStrength := cla.MoveSupport(r, self.targets[0], self.targets[1], forbiddenSupporters) + 1
		dip.Logf("'%v' vs '%v': %v", self, competingOrder, attackStrength)
		if as := cla.MoveSupport(r, competingOrder.Targets()[0], competingOrder.Targets()[1], nil) + 1; as >= attackStrength {
			if cla.MustConvoy(r, competingOrder.Targets()[0]) {
				if cla.AnyConvoyPath(r, competingOrder.Targets()[0], competingOrder.Targets()[1], true, nil) != nil {
					dip.Logf("'%v' vs '%v': %v", competingOrder, self, as)
					r.AddBounce(self.targets[0], self.targets[1])
					return cla.ErrBounce{competingOrder.Targets()[0]}
				}
			} else {
				dip.Logf("H2HDisl(%v)", self.targets[1])
				dip.Indent("  ")
				if dislodgers, _, _ := r.Find(func(p dip.Province, o dip.Order, u *dip.Unit) bool {
					res := o != nil && // is an order
						u != nil && // is a unit
						o.Type() == cla.Move && // move
						o.Targets()[1].Super() == competingOrder.Targets()[0].Super() && // against the competition
						o.Targets()[0].Super() == competingOrder.Targets()[1].Super() && // from their destination
						u.Nation != competingUnits[index].Nation // not from themselves
					if res {
						if !cla.MustConvoy(r, o.Targets()[0]) && r.Resolve(p) == nil {
							return true
						}
					}
					return false
				}); len(dislodgers) == 0 {
					dip.DeIndent()
					dip.Logf("Not dislodged")
					dip.Logf("'%v' vs '%v': %v", competingOrder, self, as)
					r.AddBounce(self.targets[0], self.targets[1])
					return cla.ErrBounce{competingOrder.Targets()[0]}
				} else {
					dip.DeIndent()
					dip.Logf("Dislodged by %v", dislodgers)
				}
			}
		} else {
			dip.Logf("'%v' vs '%v': %v", competingOrder, self, as)
		}
	}
	return nil
}
Esempio n. 8
0
func assertDATC(t *testing.T, file string) {
	in, err := os.Open(file)
	if err != nil {
		t.Fatalf("%v", err)
	}
	parser := datc.Parser{
		Variant:        "Standard",
		OrderParser:    DATCOrder,
		PhaseParser:    DATCPhase,
		NationParser:   DATCNation,
		UnitTypeParser: DATCUnitType,
		ProvinceParser: DATCProvince,
	}
	if err := parser.Parse(in, func(statePair *datc.StatePair) {
		dip.ClearLog()
		dip.Logf("Running %v", statePair.Case)
		testDATC(t, statePair)
	}); err != nil {
		t.Fatalf("%v", err)
	}
}
Esempio n. 9
0
File: phase.go Progetto: arlm/godip
func (self *phase) sortedUnits(s dip.State, n dip.Nation) (result []dip.Province, err error) {
	provs := remoteUnitSlice{
		distances: make(map[dip.Province]int),
		units:     make(map[dip.Province]dip.Unit),
	}
	provs.provinces, _, _ = s.Find(func(p dip.Province, o dip.Order, u *dip.Unit) bool {
		if u != nil && u.Nation == n {
			if provs.distances[p], err = self.shortestDistance(s, p, s.Graph().SCs(n)); err != nil {
				return false
			}
			provs.units[p] = *u
			return true
		}
		return false
	})
	if err != nil {
		return
	}
	sort.Sort(provs)
	dip.Logf("Sorted units for %v is %v", n, provs)
	result = provs.provinces
	return
}
Esempio n. 10
0
func (self *resolver) Resolve(prov common.Province) (err error) {
	common.Logf("Res(%v) (deps %v)", prov, self.deps)
	common.Indent("  ")
	var ok bool
	if err, ok = self.State.resolutions[prov]; !ok {
		if err, ok = self.guesses[prov]; !ok {
			if self.resolving[prov] {
				common.Logf("Already resolving %v, making negative guess", prov)
				err = fmt.Errorf("Negative guess")
				self.guesses[prov] = err
				self.deps = append(self.deps, prov)
			} else {
				self.resolving[prov] = true
				n_guesses := len(self.guesses)
				err = self.adjudicate(prov)
				delete(self.resolving, prov)
				if _, ok = self.guesses[prov]; ok {
					common.Logf("Guess made for %v, changing guess to positive", prov)
					self.guesses[prov] = nil
					secondErr := self.adjudicate(prov)
					delete(self.guesses, prov)
					if (err == nil) != (secondErr == nil) {
						common.Logf("Calling backup rule with %v", self.deps)
						if err = self.State.backupRule(self, self.deps); err != nil {
							return
						}
						self.deps = nil
						err = self.Resolve(prov)
					} else {
						common.Logf("Only one consistent result, returning %+v", err)
					}
				} else if len(self.guesses) != n_guesses {
					common.Logf("Made new guess, adding %v to deps", prov)
					self.deps = append(self.deps, prov)
				}
			}
		} else {
			common.Logf("Guessed")
		}
		if len(self.guesses) == 0 {
			common.Logf("No guessing, resolving %v", prov)
			self.State.resolutions[prov] = err
		}
	} else {
		common.Logf("Resolved")
	}
	common.DeIndent()
	if err == nil {
		common.Logf("%v: Success (deps %v)", prov, self.deps)
	} else {
		common.Logf("%v: Failure: %v (deps %v)", prov, err, self.deps)
	}
	return
}
Esempio n. 11
0
File: state.go Progetto: arlm/godip
func (self *State) Next() (err error) {
	/*
	   Sanitize orders.
	*/
	self.resolutions = make(map[common.Province]error)
	for prov, order := range self.orders {
		if err := order.Validate(self); err != nil {
			self.resolutions[prov] = err
			delete(self.orders, prov)
			common.Logf("Deleted %v due to %v", prov, err)
		}
	}

	/*
		Add hold to units missing orders.
	*/
	for prov, _ := range self.units {
		if _, ok := self.orders[prov]; !ok {
			if def := self.phase.DefaultOrder(prov); def != nil {
				self.orders[prov] = def
			}
		}
	}

	/*
	   Adjudicate orders.
	*/
	for prov, _ := range self.orders {
		err := self.resolver().Resolve(prov)
		self.resolutions[prov] = err
	}

	/*
	   Execute orders.
	*/
	self.movements = nil
	for prov, order := range self.orders {
		if err, ok := self.resolutions[prov]; ok && err == nil {
			order.Execute(self.resolver())
		}
	}
	self.orders = make(map[common.Province]common.Adjudicator)

	/*
	   Execute movements.
	*/
	for _, movement := range self.movements {
		if err = movement.prepare(self); err != nil {
			return
		}
	}
	for _, movement := range self.movements {
		movement.execute(self)
	}

	/*
	   Change phase.
	*/
	if err = self.phase.PostProcess(self.resolver()); err != nil {
		return
	}
	self.phase = self.phase.Next()
	return
}