A set of classes for parsing, evaluating, and formatting die roll strings.
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

SA_DiceExpression.m 8.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. //
  2. // SA_DiceExpression.m
  3. // SA_IRCBotServer
  4. //
  5. // Created by Said Achmiz on 6/23/19.
  6. //
  7. //
  8. #import "SA_DiceExpression.h"
  9. #import "SA_DiceFormatter.h"
  10. /*********************/
  11. #pragma mark Functions
  12. /*********************/
  13. NSString *NSStringFromSA_DiceExpressionOperator(SA_DiceExpressionOperator operator) {
  14. static NSDictionary <NSNumber *, NSString *> *SA_DiceExpressionOperatorStringValues;
  15. static dispatch_once_t onceToken;
  16. dispatch_once(&onceToken, ^{
  17. SA_DiceExpressionOperatorStringValues = @{ @(SA_DiceExpressionOperator_NONE) : @"SA_DB_OPERATOR_NONE",
  18. @(SA_DiceExpressionOperator_MINUS) : @"SA_DB_OPERATOR_MINUS",
  19. @(SA_DiceExpressionOperator_PLUS) : @"SA_DB_OPERATOR_PLUS",
  20. @(SA_DiceExpressionOperator_TIMES) : @"SA_DB_OPERATOR_TIMES"
  21. };
  22. });
  23. return SA_DiceExpressionOperatorStringValues[@(operator)];
  24. }
  25. NSString *NSStringFromSA_DiceExpressionRollCommand(SA_DiceExpressionRollCommand command) {
  26. static NSDictionary <NSNumber *, NSString *> *SA_DiceExpressionRollCommandStringValues;
  27. static dispatch_once_t onceToken;
  28. dispatch_once(&onceToken, ^{
  29. SA_DiceExpressionRollCommandStringValues = @{ @(SA_DiceExpressionRollCommand_SUM) : @"SA_DB_ROLL_COMMAND_SUM",
  30. @(SA_DiceExpressionRollCommand_SUM_EXPLODING) : @"SA_DB_ROLL_COMMAND_SUM_EXPLODING"
  31. };
  32. });
  33. return SA_DiceExpressionRollCommandStringValues[@(command)];
  34. }
  35. NSString *NSStringFromSA_DiceExpressionRollModifier(SA_DiceExpressionRollModifier modifier) {
  36. static NSDictionary <NSNumber *, NSString *> *SA_DiceExpressionRollModifierStringValues;
  37. static dispatch_once_t onceToken;
  38. dispatch_once(&onceToken, ^{
  39. SA_DiceExpressionRollModifierStringValues = @{ @(SA_DiceExpressionRollModifier_KEEP_HIGHEST) : @"SA_DB_ROLL_MODIFIER_KEEP_HIGHEST",
  40. @(SA_DiceExpressionRollModifier_KEEP_LOWEST) : @"SA_DB_ROLL_MODIFIER_KEEP_LOWEST"
  41. };
  42. });
  43. return SA_DiceExpressionRollModifierStringValues[@(modifier)];
  44. }
  45. NSString *NSStringFromSA_DiceExpressionError(SA_DiceExpressionError error) {
  46. static NSDictionary <NSNumber *, NSString *> *SA_DiceExpressionErrorStringValues;
  47. static dispatch_once_t onceToken;
  48. dispatch_once(&onceToken, ^{
  49. SA_DiceExpressionErrorStringValues = @{ @(SA_DiceExpressionError_ROLL_STRING_EMPTY) : @"SA_DB_ERROR_ROLL_STRING_EMPTY",
  50. @(SA_DiceExpressionError_ROLL_STRING_HAS_ILLEGAL_CHARACTERS) : @"SA_DB_ERROR_ROLL_STRING_HAS_ILLEGAL_CHARACTERS",
  51. @(SA_DiceExpressionError_UNKNOWN_ROLL_COMMAND) : @"SA_DB_ERROR_UNKNOWN_ROLL_COMMAND",
  52. @(SA_DiceExpressionError_ROLL_MODIFIER_INAPPLICABLE) : @"SA_DB_ERROR_ROLL_MODIFIER_INAPPLICABLE",
  53. @(SA_DiceExpressionError_UNKNOWN_ROLL_MODIFIER) : @"SA_DB_ERROR_UNKNOWN_ROLL_MODIFIER",
  54. @(SA_DiceExpressionError_DIE_COUNT_NEGATIVE) : @"SA_DB_ERROR_DIE_COUNT_NEGATIVE",
  55. @(SA_DiceExpressionError_DIE_COUNT_EXCESSIVE) : @"SA_DB_ERROR_DIE_COUNT_EXCESSIVE",
  56. @(SA_DiceExpressionError_DIE_SIZE_INVALID) : @"SA_DB_ERROR_DIE_SIZE_INVALID",
  57. @(SA_DiceExpressionError_DIE_SIZE_EXCESSIVE) : @"SA_DB_ERROR_DIE_SIZE_EXCESSIVE",
  58. @(SA_DiceExpressionError_UNKNOWN_OPERATOR) : @"SA_DB_ERROR_UNKNOWN_OPERATOR",
  59. @(SA_DiceExpressionError_INVALID_EXPRESSION) : @"SA_DB_ERROR_INVALID_EXPRESSION",
  60. @(SA_DiceExpressionError_INTEGER_OVERFLOW_NEGATION) : @"SA_DB_ERROR_INTEGER_OVERFLOW_NEGATION",
  61. @(SA_DiceExpressionError_INTEGER_OVERFLOW_ADDITION) : @"SA_DB_ERROR_INTEGER_OVERFLOW_ADDITION",
  62. @(SA_DiceExpressionError_INTEGER_UNDERFLOW_ADDITION) : @"SA_DB_ERROR_INTEGER_UNDERFLOW_ADDITION",
  63. @(SA_DiceExpressionError_INTEGER_OVERFLOW_SUBTRACTION) : @"SA_DB_ERROR_INTEGER_OVERFLOW_SUBTRACTION",
  64. @(SA_DiceExpressionError_INTEGER_UNDERFLOW_SUBTRACTION) : @"SA_DB_ERROR_INTEGER_UNDERFLOW_SUBTRACTION",
  65. @(SA_DiceExpressionError_INTEGER_OVERFLOW_MULTIPLICATION) : @"SA_DB_ERROR_INTEGER_OVERFLOW_MULTIPLICATION",
  66. @(SA_DiceExpressionError_INTEGER_UNDERFLOW_MULTIPLICATION) : @"SA_DB_ERROR_INTEGER_UNDERFLOW_MULTIPLICATION",
  67. @(SA_DiceExpressionError_KEEP_COUNT_EXCEEDS_ROLL_COUNT) : @"SA_DB_ERROR_KEEP_COUNT_EXCEEDS_ROLL_COUNT",
  68. @(SA_DiceExpressionError_KEEP_COUNT_NEGATIVE) : @"SA_DB_ERROR_KEEP_COUNT_NEGATIVE"
  69. };
  70. });
  71. __block NSMutableArray *errorStrings = [NSMutableArray array];
  72. [SA_DiceExpressionErrorStringValues enumerateKeysAndObjectsUsingBlock:^(NSNumber *errorKey,
  73. NSString *errorString,
  74. BOOL *stop) {
  75. if (errorKey.unsignedIntegerValue & error)
  76. [errorStrings addObject:errorString];
  77. }];
  78. return [errorStrings componentsJoinedByString:@","];
  79. // return SA_DiceExpressionErrorStringValues[@(error)];
  80. }
  81. NSComparisonResult compareEvaluatedExpressionsByResult(SA_DiceExpression *expression1,
  82. SA_DiceExpression *expression2) {
  83. if (expression1.result.integerValue < expression2.result.integerValue)
  84. return NSOrderedAscending;
  85. else if (expression1.result.integerValue > expression2.result.integerValue)
  86. return NSOrderedDescending;
  87. else
  88. return NSOrderedSame;
  89. }
  90. NSComparisonResult compareEvaluatedExpressionsByAttemptBonus(SA_DiceExpression *expression1,
  91. SA_DiceExpression *expression2) {
  92. if (expression1.rightOperand.result.integerValue < expression2.rightOperand.result.integerValue)
  93. return NSOrderedAscending;
  94. else if (expression1.rightOperand.result.integerValue > expression2.rightOperand.result.integerValue)
  95. return NSOrderedDescending;
  96. else
  97. return NSOrderedSame;
  98. }
  99. /****************************************************/
  100. #pragma mark - SA_DiceExpression class implementation
  101. /****************************************************/
  102. @implementation SA_DiceExpression
  103. +(SA_DiceExpression *) expressionByJoiningExpression:(SA_DiceExpression *)leftHandExpression
  104. toExpression:(SA_DiceExpression *)rightHandExpression
  105. withOperator:(SA_DiceExpressionOperator)operator {
  106. SA_DiceExpression *expression = [SA_DiceExpression new];
  107. // First, we check that the operands and operator are not nil. If they are,
  108. // then the expression is invalid...
  109. if ( leftHandExpression == nil
  110. || rightHandExpression == nil
  111. || operator == SA_DiceExpressionOperator_NONE
  112. ) {
  113. expression.type = SA_DiceExpressionTerm_NONE;
  114. expression.errorBitMask |= SA_DiceExpressionError_INVALID_EXPRESSION;
  115. return expression;
  116. }
  117. // If the operands and operator are present, then the expression is an
  118. // operation expression...
  119. expression.type = SA_DiceExpressionTerm_OPERATION;
  120. // ... but does it have a valid operator?
  121. if ( operator == SA_DiceExpressionOperator_MINUS
  122. || operator == SA_DiceExpressionOperator_PLUS
  123. || operator == SA_DiceExpressionOperator_TIMES
  124. ) {
  125. expression.operator = operator;
  126. } else {
  127. expression.errorBitMask |= SA_DiceExpressionError_UNKNOWN_OPERATOR;
  128. return expression;
  129. }
  130. // The operator is valid. Set the operands...
  131. expression.leftOperand = leftHandExpression;
  132. expression.rightOperand = rightHandExpression;
  133. // And inherit any errors that they may have.
  134. expression.errorBitMask |= expression.leftOperand.errorBitMask;
  135. expression.errorBitMask |= expression.rightOperand.errorBitMask;
  136. // Since this top-level expression was NOT generated by parsing an input
  137. // string, for completeness and consistency, we have to generate a fake
  138. // input string ourselves! We do this by wrapping each operand in
  139. // parentheses and putting the canonical representation of the operator
  140. // between them.
  141. // TODO: Shouldn't the canonical representation of an operator
  142. // possibly vary by formatter behavior...?
  143. // But on the other hand, how does a parser know what formatter behavior
  144. // is in use...?
  145. // TODO: Parentheses aren't even supported by the legacy parser!
  146. // This is total nonsense!
  147. expression.inputString = [NSString stringWithFormat:@"(%@)%@(%@)",
  148. expression.leftOperand.inputString,
  149. [SA_DiceFormatter canonicalRepresentationForOperator:expression.operator],
  150. expression.rightOperand.inputString];
  151. // The joining is complete. (Power overwhelming.)
  152. return expression;
  153. }
  154. /*******************************/
  155. #pragma mark - NSCopying methods
  156. /*******************************/
  157. -(instancetype) copyWithZone:(NSZone *)zone {
  158. SA_DiceExpression *copy = [SA_DiceExpression new];
  159. copy.type = _type;
  160. copy.errorBitMask = _errorBitMask;
  161. copy.operator = _operator;
  162. copy.leftOperand = [_leftOperand copy];
  163. copy.rightOperand = [_rightOperand copy];
  164. copy.rollCommand = _rollCommand;
  165. copy.dieCount = [_dieCount copy];
  166. copy.dieSize = [_dieSize copy];
  167. copy.dieType = _dieType;
  168. copy.rollModifier = _rollModifier;
  169. copy.value = _value;
  170. copy.inputString = _inputString;
  171. copy.attributedInputString = _attributedInputString;
  172. copy.result = _result;
  173. copy.rolls = _rolls;
  174. return copy;
  175. }
  176. @end