package error import ( "fmt" ) const ( ErrStorageFailure int = 1000 + iota ErrGameNotInitialized ErrGameStateInvalid ErrReportNotFound ) const ( ErrDummy int = -1 ErrDeleteShipTypeExistingGroup = 5000 ErrDeleteShipTypePlanetProduction = 5001 ErrDeleteSciencePlanetProduction = 5002 ErrMergeShipTypeNotEqual = 5003 ErrBeakGroupNumberNotEnough = 5005 ErrEntityInUse = 5006 ErrShipsBusy = 5007 ErrShipsNotOnSamePlanet = 5008 ErrUpgradeGroupNumberNotEnough = 5010 ErrUpgradeInsufficientResources = 5011 ErrSendShipHasNoDrives = 5012 ErrSendUnreachableDestination = 5013 ErrSendShipOwnerHasNoPlanets = 5014 ErrRaceExinct = 5015 ) const ( ErrInputUnknownRace int = 3000 + iota ErrInputUnknownRelation ErrInputSameRace ErrInputEntityTypeNameInvalid ErrInputNewEntityDuplicateIdentifier ErrInputEntityTypeNameEquality ErrInputEntityNotExists ErrInputEntityNotOwned ErrInputPlanetNumber ErrInputDriveValue ErrInputWeaponsValue ErrInputShieldsValue ErrInputCargoValue ErrInputShipTypeArmamentValue ErrInputShipTypeWeaponsAndArmamentValue ErrInputShipTypeZeroValues ErrInputScienceSumValues ErrInputProductionInvalid ErrInputCargoTypeInvalid ErrInputCargoLoadNotEnough ErrInputCargoLoadNotEqual ErrInputNoCargoBay ErrInputCargoLoadNoSpaceLeft ErrInputCargoUnloadEmpty ErrInputBreakGroupIllegalNumber ErrInputTechUnknown ErrInputTechInvalidMixing ErrInputUpgradeShipTechNotUsed ErrInputUpgradeParameterNotAllowed ErrInputUpgradeShipsAlreadyUpToDate ErrInputUpgradeTechLevelInsufficient ErrInputQuitCommandFollowedByCommand ErrInputUnrecognizedCommand ) func GenericErrorText(code int) string { switch code { case ErrDummy: return "Dummy" case ErrStorageFailure: return "Storage failure" case ErrGameNotInitialized: return "Game not yet initialized" case ErrGameStateInvalid: return "Invalid game state" case ErrInputUnknownRace: return "Race name is unknown to this game" case ErrInputUnknownRelation: return "Unknown relation" case ErrInputSameRace: return "Race name must be different from your own" case ErrInputEntityTypeNameInvalid: return "Name has invalid length or symbols" case ErrInputNewEntityDuplicateIdentifier: return "Entity already exists" case ErrInputEntityTypeNameEquality: return "Names should differ" case ErrInputEntityNotExists: return "Entity does not exists" case ErrInputEntityNotOwned: return "Entity is not owned" case ErrEntityInUse: return "Entity currently in use" case ErrInputPlanetNumber: return "Invalid Planet number" case ErrInputDriveValue: return "Invalid Drive value" case ErrInputWeaponsValue: return "Invalid Weapons value" case ErrInputShieldsValue: return "Invalid Shields value" case ErrInputCargoValue: return "Invalid Cargo value" case ErrInputShipTypeArmamentValue: return "Invalid Armament value" case ErrInputShipTypeWeaponsAndArmamentValue: return "Invalid Armament or Weapons value" case ErrInputShipTypeZeroValues: return "Ship type values cannot be all zeros" case ErrDeleteShipTypeExistingGroup: return "Ship type exists in a Group" case ErrDeleteShipTypePlanetProduction: return "Ship type in production on the Planet" case ErrDeleteSciencePlanetProduction: return "Science in production on the Planet" case ErrInputScienceSumValues: return "Science proportions sum should be equal 1" case ErrInputProductionInvalid: return "Invalid Production type" case ErrInputCargoTypeInvalid: return "Invalid cargo type" case ErrInputCargoLoadNotEnough: return "Not enough cargo to load" case ErrInputCargoLoadNotEqual: return "Ship(s) already loaded with another cargo" case ErrInputNoCargoBay: return "Ship type is not designed to carry cargo" case ErrInputCargoLoadNoSpaceLeft: return "No space left on the ships to load cargo" case ErrInputCargoUnloadEmpty: return "Ships are not carrying any cargo" case ErrInputBreakGroupIllegalNumber: return "Illegal ships number to make new group" case ErrMergeShipTypeNotEqual: return "Source and target ship types are not the same" case ErrBeakGroupNumberNotEnough: return "Not enough ships in the group to make a separate group" case ErrShipsBusy: return "Ship(s) are'n free to use" case ErrShipsNotOnSamePlanet: return "Ships not on the same planet" case ErrInputTechUnknown: return "Technology name unknown" case ErrInputTechInvalidMixing: return "Technologies list must containt only specific values" case ErrInputUpgradeShipTechNotUsed: return "Technology is not used with ship class" case ErrInputUpgradeParameterNotAllowed: return "Parameter not allowed for upgrade" case ErrInputUpgradeShipsAlreadyUpToDate: return "Ships already up to date, nothing to upgrade" case ErrUpgradeGroupNumberNotEnough: return "Not enough ships in the group to make an upgrade" case ErrUpgradeInsufficientResources: return "Insufficient planet production capacity" case ErrInputUpgradeTechLevelInsufficient: return "Insifficient Tech level for requested upgrade" case ErrInputQuitCommandFollowedByCommand: return "'Quit' must be the last order's command" case ErrInputUnrecognizedCommand: return "Unrecognized command" case ErrSendShipHasNoDrives: return "One or more ships are not equipped with hyperdrive and cannot be moved" case ErrSendUnreachableDestination: return "Destination planet is too far for current Drive level" case ErrSendShipOwnerHasNoPlanets: return "Race is not owning any planet, all flights impossible" case ErrRaceExinct: return "Race is extinct" default: return fmt.Sprintf("Undescribed error with code %d", code) } } type GenericError struct { Code int subject string err error } func (ge GenericError) Error() string { msg := GenericErrorText(ge.Code) if ge.subject != "" { msg += ": " + ge.subject } if ge.err != nil { msg = fmt.Errorf("%s: %w", msg, ge.err).Error() } return msg } func newGenericError(code int, arg ...any) error { e := &GenericError{Code: code} if len(arg) > 0 { i := 0 switch arg[i].(type) { case error: e.err = arg[i].(error) i += 1 } if len(arg) >= i+2 { e.subject = fmt.Sprintf(asString(arg[i]), arg[i+1:]...) } else if len(arg) == i+1 { e.subject = asString(arg[i]) } } return *e } func asString(v any) string { switch s := v.(type) { case string: return s default: return fmt.Sprint(v) } }