2
// OOLegacyScriptToJavaScriptConverterCore.m
5
// Created by Jens Ayton on 2008-08-30.
6
// Copyright 2008 Jens Ayton. All rights reserved.
9
#import "OOLegacyScriptToJavaScriptConverterCore.h"
10
#import "NSScannerOOExtensions.h"
11
#import "OOCollectionExtractors.h"
12
#import "OOJSExprNodeHelpers.h"
15
#define COMMENT_SELECTOR 0
23
kComparisonGreaterThan,
38
static NSMutableArray *ScanTokensFromString(NSString *values);
41
@interface OOLegacyScriptToJavaScriptConverter (ConverterCorePrivate)
43
- (void) convertConditional:(NSDictionary *)conditional;
45
- (void) convertOneAction:(NSString *)action;
47
- (NSString *) convertOneCondition:(NSString *)condition;
48
- (OOJSExprNode *) convertQuery:(NSString *)query gettingType:(OOOperandType *)outType;
49
- (OOJSExprNode *) convertStringCondition:(OOComparisonType)comparator comparatorString:(NSString *)comparatorString lhs:(OOJSExprNode *)lhs rhs:(OOJSExprNode *)rhs rawCondition:(NSString *)rawCondition;
50
- (OOJSExprNode *) convertNumberCondition:(OOComparisonType)comparator comparatorString:(NSString *)comparatorString lhs:(OOJSExprNode *)lhs rhs:(OOJSExprNode *)rhs rawCondition:(NSString *)rawCondition;
51
- (OOJSExprNode *) convertBoolCondition:(OOComparisonType)comparator comparatorString:(NSString *)comparatorString lhs:(OOJSExprNode *)lhs rhs:(OOJSExprNode *)rhs rawCondition:(NSString *)rawCondition;
54
- (NSString *) stringifyBooleanExpression:(NSString *)expr;
60
@implementation OOLegacyScriptToJavaScriptConverter (ConverterCore)
62
- (void) convertActions:(NSArray *)actions
66
NSAutoreleasePool *pool = nil;
68
count = [actions count];
71
for (i = 0; i != count; ++i)
73
pool = [[NSAutoreleasePool alloc] init];
75
action = [actions objectAtIndex:i];
77
if ([action isKindOfClass:[NSString class]])
79
[self convertOneAction:action];
81
else if ([action isKindOfClass:[NSDictionary class]])
83
[self convertConditional:action];
87
[self addStopIssueWithKey:@"invalid-type"
88
format:@"Expected string (action) or dictionary (conditional), but found %@.", [action class]];
89
[self appendWithFormat:@"<** Invalid object of class %@ **>", [action class]];
97
[localException raise];
104
@implementation OOLegacyScriptToJavaScriptConverter (ConverterCorePrivate)
106
- (void) convertConditional:(NSDictionary *)conditional
108
NSArray *conditions = nil;
109
NSArray *ifTrue = nil;
110
NSArray *ifFalse = nil;
112
NSString *cond = nil;
113
BOOL flipCondition = NO;
115
conditions = [conditional arrayForKey:@"conditions"];
116
ifTrue = [conditional arrayForKey:@"do"];
117
ifFalse = [conditional arrayForKey:@"else"];
119
if (ifTrue == nil && ifFalse == nil)
121
[self addWarningIssueWithKey:@"empty-conditional-action"
122
format:@"Conditional expression with neither \"do\" clause nor \"else\" clause, ignoring."];
126
if ([ifTrue count] == 0)
133
count = [conditions count];
136
[self addWarningIssueWithKey:@"empty-conditions"
137
format:@"Empty or invalid conditions array, treating as always true."];
139
// Treat as always-true for backwards-compatibility
143
[self append:@"if ("];
144
if (flipCondition) [self append:@"!("];
146
for (i = 0; i != count; ++i)
150
[self append:@" &&\n\t"];
151
if (flipCondition) [self append:@" "];
154
cond = [self convertOneCondition:[conditions objectAtIndex:i]];
157
if (_validConversion)
159
[self addBugIssueWithKey:@"unreported-error"
160
format:@"An error occurred while converting a condition, but no appropriate message was generated."];
162
cond = @"<** invalid **>";
165
if (count != 1) cond = [NSString stringWithFormat:@"(%@)", cond];
170
if (flipCondition) [self append:@")"];
171
[self append:@")\n{\n"];
175
[self convertActions:ifTrue];
177
[self append:@"}\n"];
180
[self append:@"else\n{\n"];
182
[self convertActions:ifFalse];
184
[self append:@"}\n"];
189
- (void) convertOneAction:(NSString *)action
191
NSMutableArray *tokens = nil;
192
NSString *selectorString = nil;
195
NSString *valueString = nil;
197
NSString *converted = nil;
199
// Work around one of Eric's evil hacks
200
if ([action hasPrefix:@"/*"] && [action hasSuffix:@"*/"])
202
[self append:[action stringByAppendingString:@"\n"]];
206
tokens = ScanTokensFromString(action);
208
tokenCount = [tokens count];
211
// This is a hard error in the interpreter, so it's a failure here.
212
[self addStopIssueWithKey:@"no-tokens"
213
format:@"Invalid or empty script action \"%@\"", action];
216
selectorString = [tokens objectAtIndex:0];
217
takesParam = [selectorString hasSuffix:@":"];
219
if (takesParam && tokenCount > 1)
221
if (tokenCount == 2) valueString = [tokens objectAtIndex:1];
224
[tokens removeObjectAtIndex:0];
225
valueString = [tokens componentsJoinedByString:@" "];
229
selector = NSSelectorFromString([@"convertAction_" stringByAppendingString:selectorString]);
230
if ([self respondsToSelector:selector])
234
converted = [self performSelector:selector withObject:valueString];
238
converted = [self performSelector:selector];
241
if (converted == nil)
243
if (_validConversion)
245
[self addBugIssueWithKey:@"unreported-error"
246
format:@"An error occurred while converting an action, but no appropriate message was generated (selector: \"%@\").", selectorString];
248
converted = [NSString stringWithFormat:@"<** bad %@ **>", selectorString];
252
converted = [NSString stringWithFormat:@"%@\t\t// %@", converted, selectorString];
257
converted = [NSString stringWithFormat:@"<** %@ **>\t\t// *** UNKNOWN ***", action];
258
[self addUnknownSelectorIssueWithKey:@"unknown-selector"
259
format:@"Could not convert unknown action selector \"%@\".", selectorString];
262
if ([converted length] > 0) [self appendWithFormat:@"%@\n", converted];
266
- (NSString *) convertOneCondition:(NSString *)condition
268
NSArray *tokens = nil;
269
NSString *comparisonString = nil;
270
OOComparisonType comparator = kComparisonUndefined;
272
OOJSExprNode *lhs = nil;
273
OOOperandType lhsType = kTypeInvalid;
274
NSString *rhsString = nil;
275
OOJSExprNode *rhs = nil;
276
OOJSExprNode *result = nil;
278
if (![condition isKindOfClass:[NSString class]])
280
[self addStopIssueWithKey:@"invalid-condition"
281
format:@"Condition should be string, but found %@.", [condition class]];
282
return [NSString stringWithFormat:@"<** Invalid object of class %@ **>", [condition class]];
285
tokens = ScanTokensFromString(condition);
286
tokenCount = [tokens count];
289
// This is a hard error in the interpreter, so it's a failure here.
290
[self addStopIssueWithKey:@"no-tokens"
291
format:@"Invalid or empty script condition \"%@\"", condition];
292
return @"<** invalid/empty condition **>";
295
lhs = [self convertQuery:[tokens objectAtIndex:0] gettingType:&lhsType];
299
comparisonString = [tokens objectAtIndex:1];
301
if ([comparisonString isEqualToString:@"equal"]) comparator = kComparisonEqual;
302
else if ([comparisonString isEqualToString:@"notequal"]) comparator = kComparisonNotEqual;
303
else if ([comparisonString isEqualToString:@"lessthan"]) comparator = kComparisonLessThan;
304
else if ([comparisonString isEqualToString:@"greaterthan"]) comparator = kComparisonGreaterThan;
305
else if ([comparisonString isEqualToString:@"morethan"]) comparator = kComparisonGreaterThan;
306
else if ([comparisonString isEqualToString:@"oneof"]) comparator = kComparisonOneOf;
307
else if ([comparisonString isEqualToString:@"undefined"]) comparator = kComparisonUndefined;
310
[self addStopIssueWithKey:@"invalid-comparator"
311
format:@"Unknown comparison operator \"%@\" in condition \"%@\".", comparisonString, condition];
312
return [NSString stringWithFormat:@"<** unknown comparison operator \"%@\" **>", comparisonString];
318
rhsString = [[tokens subarrayWithRange:NSMakeRange(2, tokenCount - 2)] componentsJoinedByString:@" "];
319
rhs = [self expandRightHandSide:rhsString];
322
if (lhsType == kTypeString) result = [self convertStringCondition:comparator comparatorString:comparisonString lhs:lhs rhs:rhs rawCondition:condition];
323
else if (lhsType == kTypeNumber) result = [self convertNumberCondition:comparator comparatorString:comparisonString lhs:lhs rhs:rhs rawCondition:condition];
324
else if (lhsType == kTypeBool) result = [self convertBoolCondition:comparator comparatorString:comparisonString lhs:lhs rhs:rhs rawCondition:condition];
328
[self addBugIssueWithKey:@"condition-conversion-failed"
329
format:@"Conversion of condition \"%@\" failed for unknown reasons.", condition];
330
result = EX_ERROR(@"condition conversion failed");
332
return [result jsCodeRepresentation];
336
- (OOJSExprNode *) convertStringCondition:(OOComparisonType)comparator comparatorString:(NSString *)comparatorString lhs:(OOJSExprNode *)lhs rhs:(OOJSExprNode *)rhs rawCondition:(NSString *)rawCondition
338
OOJSExprNode *parseFloatOrZero = nil;
342
case kComparisonEqual:
343
return EX_EQUAL(lhs, rhs);
345
case kComparisonNotEqual:
346
return EX_NOT_EQUAL(lhs, rhs);
348
case kComparisonLessThan:
349
[self setParseFloatOrZeroHelper];
350
parseFloatOrZero = EX_THIS_PROP(@"parseFloatOrZero");
352
if (![rhs isNumberLiteral])
354
rhs = EX_CALL(parseFloatOrZero, rhs);
356
// this.parseFloatOrZero(lhs) < rhs
357
return EX_LESS(EX_CALL(parseFloatOrZero, lhs), rhs);
359
case kComparisonGreaterThan:
360
[self setParseFloatOrZeroHelper];
361
parseFloatOrZero = EX_THIS_PROP(@"parseFloatOrZero");
363
if (![rhs isNumberLiteral])
365
rhs = EX_CALL(parseFloatOrZero, rhs);
367
// this.parseFloatOrZero(lhs) > rhs
368
return EX_GRTR(EX_CALL(parseFloatOrZero, lhs), rhs);
370
case kComparisonOneOf:
371
[self setHelperFunction:
372
@"function (string, list)\n{\n"
373
"\tlet items = list.split(\",\");\n"
374
"\treturn items.indexOf(string) != -1;\n}"
376
// this.oneOf(lhs, rhs)
377
return EX_CALL(EX_THIS_PROP(@"oneOf"), lhs, rhs);
379
case kComparisonUndefined:
380
[self setHelperFunction:
381
@"function (value)\n{\n"
382
"\treturn value == undefined || value == null;\n}"
383
forKey:@"isUndefined"];
384
// this.isUndefined(lhs)
385
return EX_CALL(EX_THIS_PROP(@"isUndefined"), lhs);
392
- (OOJSExprNode *) convertNumberCondition:(OOComparisonType)comparator comparatorString:(NSString *)comparatorString lhs:(OOJSExprNode *)lhs rhs:(OOJSExprNode *)rhs rawCondition:(NSString *)rawCondition
396
case kComparisonEqual:
397
return EX_EQUAL(lhs, rhs);
399
case kComparisonNotEqual:
400
return EX_NOT_EQUAL(lhs, rhs);
402
case kComparisonLessThan:
403
return EX_LESS(lhs, rhs);
405
case kComparisonGreaterThan:
406
return EX_GRTR(lhs, rhs);
408
case kComparisonOneOf:
409
[self setParseFloatOrZeroHelper];
410
[self setHelperFunction:
411
@"function (number, list)\n{\n"
412
"\tlet items = list.split(\",\");\n"
413
"\tfor (let i = 0; i < items.length; ++i) if (number == parseFloatOrZero(list[i])) return true;\n"
415
forKey:@"oneOfNumber"];
416
return EX_CALL(EX_THIS_PROP(@"oneOfNumber"), lhs, rhs);
418
case kComparisonUndefined:
419
[self addBugIssueWithKey:@"invalid-comparator"
420
format:@"Operator %@ is not valid for number expressions (condition: %@).", comparatorString, rawCondition];
421
return EX_ERROR_FMT(@"invalid operator %@", comparatorString);
428
- (OOJSExprNode *) convertBoolCondition:(OOComparisonType)comparator comparatorString:(NSString *)comparatorString lhs:(OOJSExprNode *)lhs rhs:(OOJSExprNode *)rhs rawCondition:(NSString *)rawCondition
430
BOOL convertedRHS = NO;
432
if ([rhs isStringLiteral])
434
NSString *rhsString = [(OOJSStringLiteralExprNode *)rhs stringValue];
435
if ([rhsString isEqual:@"YES"])
440
else if ([rhsString isEqual:@"NO"])
448
[self setHelperFunction:
449
@"function (flag)\n{\n"
450
"\t// Convert booleans to YES/NO for comparisons.\n"
451
"\treturn flag ? \"YES\" : \"NO\";\n}"
452
forKey:@"boolToString"];
454
lhs = EX_CALL(EX_THIS_PROP(@"boolToString"), lhs);
459
case kComparisonEqual:
460
if ([rhs isBooleanLiteral])
462
if ([(OOJSBoolLiteralExprNode *)rhs boolValue]) return lhs;
463
else return EX_NOT(lhs);
467
return EX_EQUAL(lhs, rhs);
470
case kComparisonNotEqual:
471
if ([rhs isBooleanLiteral])
473
if ([(OOJSBoolLiteralExprNode *)rhs boolValue]) return EX_NOT(lhs);
478
return EX_NOT_EQUAL(lhs, rhs);
481
case kComparisonLessThan:
482
case kComparisonGreaterThan:
483
case kComparisonOneOf:
484
case kComparisonUndefined:
485
[self addBugIssueWithKey:@"invalid-comparator"
486
format:@"Operator %@ is not valid for boolean expressions (condition: %@).", comparatorString, rawCondition];
487
return EX_ERROR_FMT(@"invalid operator %@", comparatorString);
494
- (OOJSExprNode *) convertQuery:(NSString *)query gettingType:(OOOperandType *)outType
497
OOJSExprNode *converted = nil;
499
assert(outType != NULL);
501
if ([query hasPrefix:@"mission_"] || [query hasPrefix:@"local_"])
503
// Variables in legacy engine are always considered strings.
504
*outType = kTypeString;
505
return [self convertVariableAccess:query];
508
if ([query hasSuffix:@"_string"]) *outType = kTypeString;
509
else if ([query hasSuffix:@"_number"]) *outType = kTypeNumber;
510
else if ([query hasSuffix:@"_bool"]) *outType = kTypeBool;
511
else *outType = kTypeInvalid;
513
selector = NSSelectorFromString([@"convertQuery_" stringByAppendingString:query]);
514
if ([self respondsToSelector:selector])
516
converted = [self performSelector:selector];
517
if (converted == nil)
519
if (_validConversion)
521
[self addBugIssueWithKey:@"unreported-error"
522
format:@"An error occurred while converting a condition, but no appropriate message was generated (selector: \"%@\").", query];
524
converted = EX_ERROR(@"unknown error");
529
[self addUnknownSelectorIssueWithKey:@"unknown-selector"
530
format:@"Could not convert unknown conditional selector \"%@\".", query];
531
converted = EX_ERROR(query);
539
- (NSString *) stringifyBooleanExpression:(NSString *)expr
541
[self setHelperFunction:
542
@"function (flag)\n{\n"
543
"\t// Convert booleans to YES/NO for comparisons.\n"
544
"\treturn flag ? \"YES\" : \"NO\";\n}"
545
forKey:@"boolToString"];
546
return [NSString stringWithFormat:@"this.boolToString(%@)", expr];
551
/*** Action handlers ***/
553
- (NSString *) convertAction_set:(NSString *)params
555
NSMutableArray *tokens = nil;
556
NSString *missionVariableString = nil;
557
NSString *valueString = nil;
559
tokens = ScanTokensFromString(params);
561
if ([tokens count] < 2)
563
[self addStopIssueWithKey:@"set-syntax-error"
564
format:@"Bad syntax for set: -- expected mission_variable or local_variable followed by value expression, got \"%@\".", params];
568
missionVariableString = [tokens objectAtIndex:0];
569
[tokens removeObjectAtIndex:0];
570
valueString = [tokens componentsJoinedByString:@" "];
572
if ([missionVariableString hasPrefix:@"mission_"] || [missionVariableString hasPrefix:@"local_"])
574
return [NSString stringWithFormat:@"%@ = %@;", [self legalizedVariableName:missionVariableString], [self expandStringOrNumber:valueString]];
578
[self addStopIssueWithKey:@"set-syntax-error"
579
format:@"Bad syntax for set: -- expected mission_variable or local_variable, got \"%@\".", missionVariableString];
585
- (NSString *) convertAction_reset:(NSString *)variable
587
NSString *legalized = [self legalizedVariableName:variable];
588
if (legalized == nil) return nil;
590
return [NSString stringWithFormat:@"%@ = null;", legalized];
594
- (NSString *) convertAction_add:(NSString *)params
596
NSMutableArray *tokens = nil;
597
NSString *missionVariableString = nil;
598
NSString *valueString = nil;
600
tokens = ScanTokensFromString(params);
602
if ([tokens count] < 2)
604
[self addStopIssueWithKey:@"add-syntax-error"
605
format:@"Bad syntax for add: -- expected mission_variable or local_variable followed by value expression, got \"%@\".", params];
609
missionVariableString = [tokens objectAtIndex:0];
610
[tokens removeObjectAtIndex:0];
611
valueString = [tokens componentsJoinedByString:@" "];
613
if ([missionVariableString hasPrefix:@"mission_"] || [missionVariableString hasPrefix:@"local_"])
615
[self setParseFloatOrZeroHelper];
616
missionVariableString = [self legalizedVariableName:missionVariableString];
617
return [NSString stringWithFormat:@"%@ = this.parseFloatOrZero(%@) + %@;", missionVariableString, missionVariableString, [self expandFloatExpression:valueString]];
621
[self addStopIssueWithKey:@"add-syntax-error"
622
format:@"Bad syntax for add: -- expected mission_variable or local_variable, got \"%@\".", missionVariableString];
628
- (NSString *) convertAction_subtract:(NSString *)params
630
NSMutableArray *tokens = nil;
631
NSString *missionVariableString = nil;
632
NSString *valueString = nil;
634
tokens = ScanTokensFromString(params);
636
if ([tokens count] < 2)
638
[self addStopIssueWithKey:@"subtract-syntax-error"
639
format:@"Bad syntax for subtract: -- expected mission_variable or local_variable followed by value expression, got \"%@\".", params];
643
missionVariableString = [tokens objectAtIndex:0];
644
[tokens removeObjectAtIndex:0];
645
valueString = [tokens componentsJoinedByString:@" "];
647
if ([missionVariableString hasPrefix:@"mission_"] || [missionVariableString hasPrefix:@"local_"])
649
[self setParseFloatOrZeroHelper];
650
missionVariableString = [self legalizedVariableName:missionVariableString];
651
return [NSString stringWithFormat:@"%@ = this.parseFloatOrZero(%@) - %@;", missionVariableString, missionVariableString, [self expandFloatExpression:valueString]];
655
[self addStopIssueWithKey:@"subtract-syntax-error"
656
format:@"Bad syntax for subtract: -- expected mission_variable or local_variable, got \"%@\".", missionVariableString];
662
- (NSString *) convertAction_increment:(NSString *)string
664
[self setParseIntOrZeroHelper];
665
NSString *varStr = [self legalizedVariableName:string];
666
return [NSString stringWithFormat:@"%@ = this.parseIntOrZero(%@) + 1;", varStr, varStr];
670
- (NSString *) convertAction_decrement:(NSString *)string
672
[self setParseIntOrZeroHelper];
673
NSString *varStr = [self legalizedVariableName:string];
674
return [NSString stringWithFormat:@"%@ = this.parseIntOrZero(%@) - 1;", varStr, varStr];
678
- (NSString *) convertAction_commsMessage:(NSString *)string
680
return [NSString stringWithFormat:@"player.commsMessage(%@);", [self expandString:string]];
684
- (NSString *) convertAction_setMissionImage:(NSString *)string
686
return [NSString stringWithFormat:@"mission.setBackgroundImage(%@);", [self expandString:string]];
690
- (NSString *) convertAction_showShipModel:(NSString *)string
692
return [NSString stringWithFormat:@"mission.showShipModel(%@);", [self expandString:string]];
696
- (NSString *) convertAction_checkForShips:(NSString *)string
698
[self setInitializer:@"this.shipsFound = 0;" forKey:@"shipsFound"];
699
return [NSString stringWithFormat:@"this.shipsFound = system.countShipsWithPrimaryRole(%@);", [self expandString:string]];
703
- (NSString *) convertAction_awardCredits:(NSString *)string
705
return [NSString stringWithFormat:@"player.credits += %@;", [self expandIntegerExpression:string]];
709
- (NSString *) convertAction_awardShipKills:(NSString *)string
711
return [NSString stringWithFormat:@"player.score += %@;", [self expandIntegerExpression:string]];
715
- (NSString *) convertAction_awardFuel:(NSString *)string
717
return [NSString stringWithFormat:@"player.ship.fuel += %@;", [self expandFloatExpression:string]];
721
- (NSString *) convertAction_addFuel:(NSString *)string
723
return [NSString stringWithFormat:@"player.ship.fuel += %@;", [self expandFloatExpression:string]];
727
- (NSString *) convertAction_setLegalStatus:(NSString *)string
729
return [NSString stringWithFormat:@"player.bounty = %@;", [self expandIntegerExpression:string]];
733
- (NSString *) convertAction_addMissionText:(NSString *)string
735
return [NSString stringWithFormat:@"mission.addMessageTextKey(%@);", [self expandString:string]];
739
- (NSString *) convertAction_setMissionChoices:(NSString *)string
741
return [NSString stringWithFormat:@"mission.setChoicesKey(%@);", [self expandString:string]];
745
- (NSString *) convertAction_useSpecialCargo:(NSString *)string
747
return [NSString stringWithFormat:@"mission.useSpecialCargo(%@);", [self expandString:string]];
751
- (NSString *) convertAction_consoleMessage3s:(NSString *)string
753
return [NSString stringWithFormat:@"player.consoleMessage(%@);", [self expandString:string]];
757
- (NSString *) convertAction_consoleMessage6s:(NSString *)string
759
return [NSString stringWithFormat:@"player.consoleMessage(%@, 6.0);", [self expandString:string]];
763
- (NSString *) convertAction_testForEquipment:(NSString *)string
765
[self setInitializer:@"this.foundEqipment = false;" forKey:@"foundEqipment"];
766
return [NSString stringWithFormat:@"this.foundEqipment = player.ship.hasEquipment(%@);", [self expandString:string]];
770
- (NSString *) convertAction_awardEquipment:(NSString *)string
772
return [NSString stringWithFormat:@"player.ship.awardEquipment(%@);", [self expandString:string]];
776
- (NSString *) convertAction_removeEquipment:(NSString *)string
778
return [NSString stringWithFormat:@"player.ship.removeEquipment(%@);", [self expandString:string]];
782
- (NSString *) convertAction_setFuelLeak:(NSString *)string
784
return [NSString stringWithFormat:@"player.ship.fuelLeakRate = %@;", [self expandFloatExpression:string]];
788
- (NSString *) convertAction_setSunNovaIn:(NSString *)string
790
return [NSString stringWithFormat:@"system.sun.goNova(%@);", [self expandFloatExpression:string]];
794
- (NSString *) convertAction_setMissionDescription:(NSString *)string
796
return [NSString stringWithFormat:@"mission.setInstructionsKey(%@);", [self expandString:string]];
800
- (NSString *) convertAction_clearMissionDescription
802
return [NSString stringWithFormat:@"mission.setInstructionsKey(null);"];
806
- (NSString *) convertAction_setMissionMusic:(NSString *)string
808
return [NSString stringWithFormat:@"mission.setMusic(%@);", [self expandString:string]];
812
- (NSString *) convertAction_addMissionDestination:(NSString *)string
814
/* expandStringOrNumber: is used because more than one destination can be
815
specified, as a space-separated list. mission.markSystem() supports
816
this format, as well as comma-separated lists.
818
return [NSString stringWithFormat:@"mission.markSystem(%@);", [self expandStringOrNumber:string]];
822
- (NSString *) convertAction_removeMissionDestination:(NSString *)string
824
/* expandStringOrNumber: is used because more than one destination can be
825
specified, as a space-separated list. mission.unmarkSystem() supports
826
this format, as well as comma-separated lists.
828
return [NSString stringWithFormat:@"mission.unmarkSystem(%@);", [self expandStringOrNumber:string]];
832
- (NSString *) convertAction_addShips:(NSString *)params
834
NSMutableArray *tokens = nil;
835
NSString *roleString = nil;
836
NSString *countString = nil;
838
tokens = ScanTokensFromString(params);
839
if ([tokens count] != 2)
841
[self addStopIssueWithKey:@"addShips-syntax-error"
842
format:@"Bad syntax for addShips: -- expected role followed by count, got \"%@\".", params];
846
roleString = [tokens objectAtIndex:0];
847
countString = [tokens objectAtIndex:1];
849
return [NSString stringWithFormat:@"system.legacy_addShips(%@, %@);",
850
[self expandString:roleString],
851
[self expandIntegerExpression:countString]];
855
- (NSString *) convertAction_addSystemShips:(NSString *)params
857
NSMutableArray *tokens = nil;
858
NSString *roleString = nil;
859
NSString *countString = nil;
860
NSString *positionString = nil;
862
tokens = ScanTokensFromString(params);
863
if ([tokens count] != 3)
865
[self addStopIssueWithKey:@"addSystemShips-syntax-error"
866
format:@"Bad syntax for addSystemShips: -- expected <role> <count> <position>, got \"%@\".", params];
870
roleString = [tokens objectAtIndex:0];
871
countString = [tokens objectAtIndex:1];
872
positionString = [tokens objectAtIndex:2];
874
return [NSString stringWithFormat:@"system.legacy_addSystemShips(%@, %@, %@);",
875
[self expandString:roleString],
876
[self expandIntegerExpression:countString],
877
[self expandFloatExpression:positionString]];
881
- (NSString *) convertAction_addShipsAt:(NSString *)params
883
NSMutableArray *tokens = nil;
884
NSString *roleString = nil;
885
NSString *countString = nil;
886
NSString *systemString = nil;
887
NSString *xString = nil;
888
NSString *yString = nil;
889
NSString *zString = nil;
891
tokens = ScanTokensFromString(params);
892
if ([tokens count] != 6)
894
[self addStopIssueWithKey:@"addShipsAt-syntax-error"
895
format:@"Bad syntax for addShipsAt: -- expected <role> <count> <coordinate-system> <x> <y> <z>, got \"%@\".", params];
899
roleString = [tokens objectAtIndex:0];
900
countString = [tokens objectAtIndex:1];
901
systemString = [tokens objectAtIndex:2];
902
xString = [tokens objectAtIndex:3];
903
yString = [tokens objectAtIndex:4];
904
zString = [tokens objectAtIndex:5];
906
return [NSString stringWithFormat:@"system.legacy_addShipsAt(%@, %@, %@, [%@, %@, %@]);",
907
[self expandString:roleString],
908
[self expandIntegerExpression:countString],
909
[self expandString:systemString],
910
[self expandFloatExpression:xString],
911
[self expandFloatExpression:yString],
912
[self expandFloatExpression:zString]];
916
- (NSString *) convertAction_addShipsAtPrecisely:(NSString *)params
918
NSMutableArray *tokens = nil;
919
NSString *roleString = nil;
920
NSString *countString = nil;
921
NSString *systemString = nil;
922
NSString *xString = nil;
923
NSString *yString = nil;
924
NSString *zString = nil;
926
tokens = ScanTokensFromString(params);
927
if ([tokens count] != 6)
929
[self addStopIssueWithKey:@"addShipsAtPrecisely-syntax-error"
930
format:@"Bad syntax for addShipsAtPrecisely: -- expected <role> <count> <coordinate-system> <x> <y> <z>, got \"%@\".", params];
934
roleString = [tokens objectAtIndex:0];
935
countString = [tokens objectAtIndex:1];
936
systemString = [tokens objectAtIndex:2];
937
xString = [tokens objectAtIndex:3];
938
yString = [tokens objectAtIndex:4];
939
zString = [tokens objectAtIndex:5];
941
return [NSString stringWithFormat:@"system.legacy_addShipsAtPrecisely(%@, %@, %@, [%@, %@, %@]);",
942
[self expandString:roleString],
943
[self expandIntegerExpression:countString],
944
[self expandString:systemString],
945
[self expandFloatExpression:xString],
946
[self expandFloatExpression:yString],
947
[self expandFloatExpression:zString]];
951
- (NSString *) convertAction_addShipsWithinRadius:(NSString *)params
953
NSMutableArray *tokens = nil;
954
NSString *roleString = nil;
955
NSString *countString = nil;
956
NSString *systemString = nil;
957
NSString *xString = nil;
958
NSString *yString = nil;
959
NSString *zString = nil;
960
NSString *radiusString = nil;
962
tokens = ScanTokensFromString(params);
963
if ([tokens count] != 7)
965
[self addStopIssueWithKey:@"addShipsWithinRadius-syntax-error"
966
format:@"Bad syntax for addShipsWithinRadius: -- expected <role> <count> <coordinate-system> <x> <y> <z> <radius>, got \"%@\".", params];
970
roleString = [tokens objectAtIndex:0];
971
countString = [tokens objectAtIndex:1];
972
systemString = [tokens objectAtIndex:2];
973
xString = [tokens objectAtIndex:3];
974
yString = [tokens objectAtIndex:4];
975
zString = [tokens objectAtIndex:5];
976
radiusString = [tokens objectAtIndex:6];
978
return [NSString stringWithFormat:@"system.legacy_addShipsWithinRadius(%@, %@, %@, [%@, %@, %@], %@);",
979
[self expandString:roleString],
980
[self expandIntegerExpression:countString],
981
[self expandString:systemString],
982
[self expandFloatExpression:xString],
983
[self expandFloatExpression:yString],
984
[self expandFloatExpression:zString],
985
[self expandFloatExpression:radiusString]];
989
- (NSString *) convertAction_awardCargo:(NSString *)params
991
NSMutableArray *tokens = nil;
992
NSString *quantityString = nil;
993
NSString *typeString = nil;
995
tokens = ScanTokensFromString(params);
996
if ([tokens count] != 2)
998
[self addStopIssueWithKey:@"awardCargo-syntax-error"
999
format:@"Bad syntax for awardCargo: -- expected count followed by type, got \"%@\".", params];
1003
quantityString = [tokens objectAtIndex:0];
1004
typeString = [tokens objectAtIndex:1];
1006
if ([quantityString isEqualToString:@"1"])
1008
return [NSString stringWithFormat:@"player.ship.awardCargo(%@);", [self expandString:typeString]];
1012
return [NSString stringWithFormat:@"player.ship.awardCargo(%@, %@);", [self expandString:typeString], [self expandIntegerExpression:quantityString]];
1017
- (NSString *) convertAction_setPlanetinfo:(NSString *)params
1019
NSArray *tokens = nil;
1020
NSString *keyString = nil;
1021
NSString *valueString = nil;
1023
tokens = [params componentsSeparatedByString:@"="];
1024
if ([tokens count] != 2)
1026
[self addStopIssueWithKey:@"setPlanetinfo-syntax-error"
1027
format:@"Bad syntax for setPlanetinfo: -- expected key=value, got \"%@\".", params];
1031
keyString = [[tokens objectAtIndex:0] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
1032
valueString = [[tokens objectAtIndex:1] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
1034
return [NSString stringWithFormat:@"system.info%@ = %@;", [self expandPropertyReference:keyString], [self expandString:valueString]];
1038
- (NSString *) convertAction_setSpecificPlanetInfo:(NSString *)params
1040
NSArray *tokens = nil;
1041
NSString *galaxyString = nil;
1042
NSString *systemString = nil;
1043
NSString *keyString = nil;
1044
NSString *valueString = nil;
1046
tokens = [params componentsSeparatedByString:@"="];
1047
if ([tokens count] != 4)
1049
[self addStopIssueWithKey:@"setPlanetinfo-syntax-error"
1050
format:@"Bad syntax for setSpecificPlanetInfo: -- expected galaxy=system=key=value, got \"%@\".", params];
1054
galaxyString = [[tokens objectAtIndex:0] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
1055
systemString = [[tokens objectAtIndex:1] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
1056
keyString = [[tokens objectAtIndex:2] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
1057
valueString = [[tokens objectAtIndex:3] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
1059
return [NSString stringWithFormat:@"System.infoForSystem(%@, %@)%@ = %@;", [self expandIntegerExpression:galaxyString], [self expandIntegerExpression:systemString], [self expandPropertyReference:keyString], [self expandString:valueString]];
1063
- (NSString *) convertAction_sendAllShipsAway
1065
return @"system.sendAllShipsAway();";
1069
- (NSString *) convertAction_launchFromStation
1071
return @"player.ship.launch();";
1075
- (NSString *) convertAction_blowUpStation
1077
return @"system.mainStation.explode();";
1081
- (NSString *) convertAction_removeAllCargo
1083
return @"player.ship.removeAllCargo();";
1087
- (NSString *) convertAction_clearMissionScreen
1089
return @"mission.clearMissionScreen();";
1093
- (NSString *) convertAction_setGuiToMissionScreen
1095
return @"mission.showMissionScreen();";
1099
- (NSString *) convertAction_resetMissionChoice
1101
return @"mission.choice = null;";
1105
- (NSString *) convertAction_setGuiToStatusScreen
1107
// FIXME: is this OK in general?
1112
- (NSString *) convertAction_debugOn
1114
return @"if (debugConsole) debugConsole.setDisplayMessagesInClass(\"$scriptDebugOn\", true);";
1118
- (NSString *) convertAction_debugOff
1120
return @"if (debugConsole) debugConsole.setDisplayMessagesInClass(\"$scriptDebugOn\", false);";
1124
/*** Query handlers ***/
1126
- (OOJSExprNode *) convertQuery_dockedAtMainStation_bool
1128
/* player.ship.docked && player.ship.dockedStation == system.mainStation
1129
(player.ship.docked is required, because player.ship.dockedStation ==
1130
system.mainStation is true in interstellar space.)
1132
return EX_AND(EX_PROP(EX_PROP(@"player", @"ship"), @"docked"), EX_EQUAL(EX_PROP(EX_PROP(@"player", @"ship"), @"dockedStation"), EX_PROP(@"system", @"mainStation")));
1136
- (OOJSExprNode *) convertQuery_galaxy_number
1138
return EX_ID(@"galaxyNumber");
1142
- (OOJSExprNode *) convertQuery_planet_number
1144
return EX_PROP(@"system", @"ID");
1148
- (OOJSExprNode *) convertQuery_score_number
1150
return EX_PROP(@"player", @"score");
1154
- (OOJSExprNode *) convertQuery_d100_number
1156
// Math.floor(Math.random() * 256)
1157
return EX_CALL(EX_PROP(@"Math", @"floor"), EX_MULTIPLY(EX_VOID_CALL(EX_PROP(@"Math", @"random")), EX_INT(100)));
1161
- (OOJSExprNode *) convertQuery_d256_number
1163
// Math.floor(Math.random() * 256)
1164
return EX_CALL(EX_PROP(@"Math", @"floor"), EX_MULTIPLY(EX_VOID_CALL(EX_PROP(@"Math", @"random")), EX_INT(256)));
1168
- (OOJSExprNode *) convertQuery_sunWillGoNova_bool
1170
return EX_PROP(EX_PROP(@"system", @"sun"), @"isGoingNova");
1174
- (OOJSExprNode *) convertQuery_sunGoneNova_bool
1176
return EX_PROP(EX_PROP(@"system", @"sun"), @"hasGoneNova");
1180
- (OOJSExprNode *) convertQuery_status_string
1182
return EX_PROP(EX_PROP(@"player", @"ship"), @"status");
1186
- (OOJSExprNode *) convertQuery_shipsFound_number
1188
[self setInitializer:@"this.shipsFound = 0;" forKey:@"shipsFound"];
1189
return EX_THIS_PROP(@"shipsFound");
1193
- (OOJSExprNode *) convertQuery_foundEquipment_bool
1195
[self setInitializer:@"this.foundEqipment = false;" forKey:@"foundEqipment"];
1196
return EX_THIS_PROP(@"foundEqipment");
1200
- (OOJSExprNode *) convertQuery_missionChoice_string
1202
return EX_PROP(@"mission", @"choice");
1206
- (OOJSExprNode *) convertQuery_scriptTimer_number
1208
return EX_PROP(@"clock", @"legacy_scriptTimer");
1212
- (OOJSExprNode *) convertQuery_gui_screen_string
1214
return EX_ID(@"guiScreen");
1218
- (OOJSExprNode *) convertQuery_credits_number
1220
return EX_PROP(@"player", @"credits");
1224
- (OOJSExprNode *) convertQuery_dockedStationName_string
1227
this.dockedStationName = function ()
1229
if (player.ship.docked)
1231
var result = player.ship.dockedStation.name;
1232
if (!result) result = "UNKNOWN";
1237
var result = "NONE";
1242
[self setHelperFunction:
1244
"\tif (player.ship.docked)\n\t{\n"
1245
"\t\tvar result = player.ship.dockedStation.name;\n"
1246
"\t\tif (!result) result = \"UNKNOWN\";\n"
1247
"\t}\n\telse\n\t{\n"
1248
"\t\tvar result = \"NONE\";\n\t}\n"
1249
"\treturn result;\n}"
1250
forKey:@"dockedStationName"];
1252
return EX_VOID_CALL(EX_THIS_PROP(@"dockedStationName"));
1256
- (OOJSExprNode *) convertQuery_systemGovernment_string
1258
return EX_PROP(@"system", @"governmentDescription");
1262
- (OOJSExprNode *) convertQuery_systemGovernment_number
1264
return EX_PROP(@"system", @"government");
1268
- (OOJSExprNode *) convertQuery_systemEconomy_string
1270
return EX_PROP(@"system", @"economyDescription");
1274
- (OOJSExprNode *) convertQuery_systemEconomy_number
1276
return EX_PROP(@"system", @"economy");
1280
- (OOJSExprNode *) convertQuery_systemTechLevel_number
1282
return EX_PROP(@"system", @"techLevel");
1286
- (OOJSExprNode *) convertQuery_systemPopulation_number
1288
return EX_PROP(@"system", @"population");
1292
- (OOJSExprNode *) convertQuery_systemProductivity_number
1294
return EX_PROP(@"system", @"productivity");
1298
- (OOJSExprNode *) convertQuery_commanderName_string
1300
return EX_PROP(@"player", @"name");
1304
- (OOJSExprNode *) convertQuery_commanderRank_string
1306
return EX_PROP(@"player", @"rank");
1310
- (OOJSExprNode *) convertQuery_commanderShip_string
1312
return EX_PROP(EX_PROP(@"player", @"ship"), @"name");
1316
- (OOJSExprNode *) convertQuery_commanderShipDisplayName_string
1318
return EX_PROP(EX_PROP(@"player", @"ship"), @"displayName");
1323
- (OOJSExprNode *) convertQuery_commanderLegalStatus_string
1325
return EX_PROP(@"player", @"legalStatus");
1329
- (OOJSExprNode *) convertQuery_commanderLegalStatus_number
1331
return EX_PROP(@"player", @"bounty");
1335
- (OOJSExprNode *) convertQuery_legalStatus_number
1337
return EX_PROP(@"player", @"bounty");
1341
- (OOJSExprNode *) convertQuery_pseudoFixedD100_number
1343
return EX_PROP(@"system", @"psuedoRandom100");
1347
- (OOJSExprNode *) convertQuery_pseudoFixedD256_number
1349
return EX_PROP(@"system", @"psuedoRandom256");
1355
static NSMutableArray *ScanTokensFromString(NSString *values)
1357
NSMutableArray *result = nil;
1358
NSScanner *scanner = nil;
1359
NSString *token = nil;
1360
static NSCharacterSet *space_set = nil;
1362
if (values == nil) return [NSArray array];
1363
if (space_set == nil) space_set = [[NSCharacterSet whitespaceAndNewlineCharacterSet] retain];
1365
result = [NSMutableArray array];
1366
scanner = [NSScanner scannerWithString:values];
1368
while (![scanner isAtEnd])
1370
[scanner ooliteScanCharactersFromSet:space_set intoString:NULL];
1371
if ([scanner ooliteScanUpToCharactersFromSet:space_set intoString:&token])
1373
[result addObject:token];