func (self *Phase) Options(nation dip.Nation) (result dip.Options, err error) { state, err := self.State() if err != nil { return } result = state.Phase().Options(state, nation) return }
func (self *Game) resolve(c common.SkinnyContext, phase *Phase) (err error) { // Check that we are in a phase where we CAN resolve if self.State != common.GameStateStarted { err = fmt.Errorf("%+v is not started", self) return } // Load our members members, err := self.Members(c.DB()) if err != nil { return } // Load the godip state for the phase state, err := phase.State() if err != nil { return } // Load "now" epoch, err := epoch.Get(c.DB()) if err != nil { return } // Just to limit runaway resolution to 100 phases. for i := 0; i < 100; i++ { // Resolve the phase! if err = state.Next(); err != nil { return } // Load the new godip phase from the state nextDipPhase := state.Phase() // Create a diplicity phase for the new phase nextPhase := &Phase{ GameId: self.Id, Ordinal: phase.Ordinal + 1, Orders: map[dip.Nation]map[dip.Province][]string{}, Resolutions: map[dip.Province]string{}, Season: nextDipPhase.Season(), Year: nextDipPhase.Year(), Type: nextDipPhase.Type(), Deadline: epoch + (time.Minute * time.Duration(self.Deadlines[nextDipPhase.Type()])), } // Set the new phase positions var resolutions map[dip.Province]error nextPhase.Units, nextPhase.SupplyCenters, nextPhase.Dislodgeds, nextPhase.Dislodgers, nextPhase.Bounces, resolutions = state.Dump() // Store the results of the previous godip phase in the previous diplicity phase for _, nationOrders := range phase.Orders { for prov, _ := range nationOrders { if res, found := resolutions[prov]; found && res != nil { phase.Resolutions[prov] = res.Error() } else { phase.Resolutions[prov] = "OK" } } } // Commit everyone that doesn't have any orders to give waitFor := []*Member{} active := []*Member{} nonSurrendering := []*Member{} for index, _ := range members { opts := dip.Options{} if opts, err = nextPhase.Options(members[index].Nation); err != nil { return } if err = self.endPhaseConsequences(c, phase, &members[index], opts, &waitFor, &active, &nonSurrendering); err != nil { return } } // Mark the old phase as resolved, and save it phase.Resolved = true if err = c.DB().Set(phase); err != nil { return } // If we have a solo victor, end and return if winner := nextDipPhase.Winner(state); winner != nil { var winnerMember *Member for _, member := range members { if member.Nation == *winner { winnerMember = &member break } } if winnerMember == nil { err = fmt.Errorf("None of %+v has nation %#v??", members, *winner) return } if err = self.end(c, nextPhase, members, winnerMember, common.SoloVictory(*winner)); err != nil { return } return } // End the game now if nobody is active anymore if len(active) == 0 { if err = self.end(c, nextPhase, members, nil, common.ZeroActiveMembers); err != nil { return } return } // End the game now if only one player isn't surrendering if len(nonSurrendering) == 1 { if err = self.end(c, nextPhase, members, nonSurrendering[0], common.SoloVictory(nonSurrendering[0].Nation)); err != nil { return } return } // Store the next phase if err = c.DB().Set(nextPhase); err != nil { return } // If there is anyone we need to wait for, schedule an auto resolve and return here. if len(waitFor) > 0 { if err = nextPhase.Schedule(c); err != nil { return } nextPhase.SendScheduleEmails(c, self) return } phase = nextPhase } return }