about summary refs log tree commit diff stats
path: root/data/maps/daedalus/rooms/Composite Room NE.txtpb
blob: c91a06f46dd59da5e247019f3cb0656e0f975c32 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
name: "Composite Room NE"
panel_display_name: "Composite Room"
panels {
  name: "<-"
  path: "Panels/Combo Room NE/panel_1"
  clue: ""
  answer: "workbook"
  symbols: LINGO
}
panels {
  name: "TEXTBOOK"
  path: "Panels/Combo Room NE/panel_2"
  clue: "textbook"
  answer: "bookstore"
  symbols: EXAMPLE
}
panels {
  name: "CORNERHOME"
  path: "Panels/Combo Room NE/panel_3"
  clue: "cornerhome"
  answer: "storehouse"
  symbols: SUN
  symbols: EXAMPLE
}
panels {
  name: "BIRDCALL"
  path: "Panels/Combo Room NE/panel_4"
  clue: "birdcall"
  answer: "housework"
  symbols: EXAMPLE
}
panels {
  name: "FORCEYARD"
  path: "Panels/Combo Room NE/panel_6"
  clue: "forceyard"
  answer: "massacre"
  symbols: BOXES
}
panels {
  name: "TIREPOUND"
  path: "Panels/Combo Room NE/panel_7"
  clue: "tirepound"
  answer: "carton"
  symbols: BOXES
}
panels {
  name: "LIEQUIZ"
  path: "Panels/Combo Room NE/panel_8"
  clue: "liequiz"
  answer: "contest"
  symbols: SUN
  symbols: PYRAMID
}
panels {
  name: "WHITEOUT"
  path: "Panels/Combo Room NE/panel_9"
  clue: "whiteout"
  answer: "within"
  symbols: SUN
  symbols: SPARKLES
}
panels {
  name: "FEETHIM"
  path: "Panels/Combo Room NE/panel_10"
  clue: "feethim"
  answer: "feather"
  symbols: ZERO
  symbols: GENDER
}
panels {
  name: "STARFALL"
  path: "Panels/Combo Room NE/panel_11"
  clue: "starfall"
  answer: "sunrise"
  symbols: SUN
  symbols: EXAMPLE
}
5px; } td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } .highlight .hll { background-color: #ffffcc } .highlight .c { color: #888888 } /* Comment */ .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ .highlight .k { color: #008800; font-weight: bold } /* Keyword */ .highlight .ch { color: #888888 } /* Comment.Hashbang */ .highlight .cm { color: #888888 } /* Comment.Multiline */ .highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */ .highlight .cpf { color: #888888 } /* Comment.PreprocFile */ .highlight .c1 { color: #888888 } /* Comment.Single */ .highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */ .highlight .gr { color: #aa0000 } /* Generic.Error */ .highlight .gh { color: #333333 } /* Generic.Heading */ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
/*
 * cocos2d for iPhone: http://www.cocos2d-iphone.org
 *
 * Copyright (c) 2008-2010 Ricardo Quesada
 * Copyright (c) 2011 Zynga Inc.
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 */


#import "CLScoreServerPost.h"
#import "ccMacros.h"

// free function used to sort
NSInteger alphabeticSort(id string1, id string2, void *reverse);

NSInteger alphabeticSort(id string1, id string2, void *reverse)
{
    if ((NSInteger *)reverse == NO)
        return [string2 localizedCaseInsensitiveCompare:string1];
    return [string1 localizedCaseInsensitiveCompare:string2];
}


@interface CLScoreServerPost (Private)
-(void) addValue:(NSString*)value key:(NSString*)key;
-(void) calculateHashAndAddValue:(id)value key:(NSString*)key;
-(NSString*) getHashForData;
-(NSData*) getBodyValues;
-(NSString*) encodeData:(NSString*)data;
-(NSMutableURLRequest *) scoreServerRequestWithURLString:(NSString *)url;
-(BOOL) submitScore:(NSDictionary*)dict forUpdate:(BOOL)isUpdate;
@end


@implementation CLScoreServerPost

@synthesize postStatus = postStatus_;
@synthesize ranking = ranking_;
@synthesize scoreDidUpdate = scoreDidUpdate_;
@synthesize connection = connection_;

+(id) serverWithGameName:(NSString*) name gameKey:(NSString*) key delegate:(id) delegate
{
	return [[[self alloc] initWithGameName:name gameKey:key delegate:delegate] autorelease];
}

-(id) initWithGameName:(NSString*) name gameKey:(NSString*) key delegate:(id)aDelegate
{
	self = [super init];
	if( self ) {
		gameKey = [key retain];
		gameName = [name retain];
		bodyValues = [[NSMutableArray arrayWithCapacity:5] retain];
		delegate = [aDelegate retain];
		receivedData = [[NSMutableData data] retain];
		
		ranking_ = kServerPostInvalidRanking;
	}
	
	return self;
}

-(void) dealloc
{
	CCLOGINFO(@"deallocing %@", self);
	[delegate release];
	[gameKey release];
	[gameName release];
	[bodyValues release];
	[receivedData release];
	[connection_ release];
	[super dealloc];
}


#pragma mark ScoreServer send scores
-(BOOL) sendScore: (NSDictionary*) dict 
{
    return [self submitScore:dict forUpdate:NO];
}

-(BOOL) updateScore: (NSDictionary*) dict
{	
    if (![dict objectForKey:@"cc_playername"]) {
		// fail. cc_playername + cc_device_id are needed to update an score
		[NSException raise:@"cocosLive:updateScore" format:@"cc_playername not found"]; 
	}
    return [self submitScore:dict forUpdate:YES];
}

-(BOOL) submitScore: (NSDictionary*)dict forUpdate:(BOOL)isUpdate
{	
    [receivedData setLength:0];
	[bodyValues removeAllObjects];
	
	// reset status
	postStatus_ = kPostStatusOK;
		
	// create the request
	NSMutableURLRequest *post = [self scoreServerRequestWithURLString:(isUpdate ? SCORE_SERVER_UPDATE_URL : SCORE_SERVER_SEND_URL)];
	
	CC_MD5_Init( &md5Ctx);

    // hash SHALL be calculated in certain order
	NSArray *keys = [dict allKeys];
	int reverseSort = NO;
	NSArray *sortedKeys = [keys sortedArrayUsingFunction:alphabeticSort context:&reverseSort];
	for( id key in sortedKeys )
		[self calculateHashAndAddValue:[dict objectForKey:key] key:key];    

    // device id is hashed to prevent spoofing this same score from different devices
	// one way to prevent a replay attack is to send cc_id & cc_time and use it as primary keys
    
	[self addValue:[[UIDevice currentDevice] uniqueIdentifier] key:@"cc_device_id"];
	[self addValue:gameName key:@"cc_gamename"];
	[self addValue:[self getHashForData] key:@"cc_hash"];
	[self addValue:SCORE_SERVER_PROTOCOL_VERSION key:@"cc_prot_ver"];
    
	[post setHTTPBody: [self getBodyValues] ];
	
	// create the connection with the request
	// and start loading the data
	self.connection=[NSURLConnection connectionWithRequest:post delegate:self];
	
	if ( ! connection_)
		return NO;
	
	return YES;
}

-(NSMutableURLRequest *) scoreServerRequestWithURLString:(NSString *)url {
    NSMutableURLRequest *request=[NSMutableURLRequest requestWithURL:[NSURL URLWithString: url]
                                                      cachePolicy:NSURLRequestUseProtocolCachePolicy
                                                  timeoutInterval:10.0];
	
	[request setHTTPMethod: @"POST"];
	[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
    return request;
}

-(void) calculateHashAndAddValue:(id) value key:(NSString*) key
{
	NSString *val;
	// value shall be a string or nsnumber
	if( [value respondsToSelector:@selector(stringValue)] )
		val = [value stringValue];
	else if( [value isKindOfClass:[NSString class]] )
		val = value;
	else
		[NSException raise:@"Invalid format for value" format:@"Invalid format for value. addValue"];

	[self addValue:val key:key];
	
	const char * data = [val UTF8String];
	CC_MD5_Update( &md5Ctx, data, strlen(data) );
}

-(void) addValue:(NSString*)value key:(NSString*) key
{

	NSString *encodedValue = [self encodeData:value];
	NSString *encodedKey = [self encodeData:key];
		
	[bodyValues addObject: [NSString stringWithFormat:@"%@=%@", encodedKey, encodedValue] ];
}

-(NSData*) getBodyValues {
	NSMutableData *data = [[NSMutableData alloc] init];
	
	BOOL first=YES;
	for( NSString *s in bodyValues ) {
		if( !first)
			[data appendBytes:"&" length:1];
		
		[data appendBytes:[s UTF8String] length:[s length]];
		first = NO;
	}
	
	return [data autorelease];
}

-(NSString*) getHashForData
{
	NSString *ret;
	unsigned char  pTempKey[16];
	
	// update the hash with the secret key
	const char *data = [gameKey UTF8String];
	CC_MD5_Update(&md5Ctx, data, strlen(data));
	
	// then get the hash
	CC_MD5_Final( pTempKey, &md5Ctx);

//	NSData *nsdata = [NSData dataWithBytes:pTempKey length:16];
	ret = [NSString stringWithString:@""];
	for( int i=0;i<16;i++) {
		ret = [NSString stringWithFormat:@"%@%02x", ret, pTempKey[i] ];
	}

	return ret;
}

-(NSString*) encodeData:(NSString*) data
{
	NSString *newData;
	
	newData = [data stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

	// '&' and '=' should be encoded manually
	newData = [newData stringByReplacingOccurrencesOfString:@"&" withString:@"%26"];
	newData = [newData stringByReplacingOccurrencesOfString:@"=" withString:@"%3D"];

	return newData;
}

#pragma mark NSURLConnection Delegate

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    // this method is called when the server has determined that it
    // has enough information to create the NSURLResponse
	
    // it can be called multiple times, for example in the case of a
    // redirect, so each time we reset the data.
    // receivedData is declared as a method instance elsewhere
    [receivedData setLength:0];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    // append the new data to the receivedData
    // receivedData is declared as a method instance elsewhere
	[receivedData appendData:data];
	
//	NSString *dataString = [NSString stringWithCString:[data bytes] length: [data length]];
//	CCLOG( @"data: %@", dataString);
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
	CCLOG(@"Connection failed");

	// wifi problems ?
	postStatus_ = kPostStatusConnectionFailed;

    // release the connection
	self.connection = nil;
	
	if( [delegate respondsToSelector:@selector(scorePostFail:) ] )
		[delegate scorePostFail:self];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{	
	// release the connection
	self.connection = nil;
	
//	NSString *dataString = [NSString stringWithCString:[receivedData bytes] length: [receivedData length]];
	NSString *dataString = [NSString stringWithCString:[receivedData bytes] encoding: NSASCIIStringEncoding];
	
	if( [dataString hasPrefix:@"OK:"] ) {
		// parse ranking and other possible answers
		NSArray *values = [dataString componentsSeparatedByString:@":"];
		NSArray *answer = [ [values objectAtIndex:1] componentsSeparatedByString:@","];
		NSEnumerator *nse = [answer objectEnumerator];
		
		// Create a holder for each line we are going to work with
		NSString *line;
		
		// Loop through all the lines in the lines array processing each one
		while( (line = [nse nextObject]) ) {
			NSArray *keyvalue = [line componentsSeparatedByString:@"="];
//			NSLog(@"%@",keyvalue);
			if( [[keyvalue objectAtIndex:0] isEqual:@"ranking"] ) {
				ranking_ = [[keyvalue objectAtIndex:1] intValue];
			} else if( [[keyvalue objectAtIndex:0] isEqual:@"score_updated"] ) {
				scoreDidUpdate_ = [[keyvalue objectAtIndex:1] boolValue];
			}
			
		}
		if( [delegate respondsToSelector:@selector(scorePostOk:) ] )
			[delegate scorePostOk:self];
	
	} else if( [dataString hasPrefix: @"OK"] ) {
			
		// Ok
		postStatus_ = kPostStatusOK;
		
		if( [delegate respondsToSelector:@selector(scorePostOk:) ] )
			[delegate scorePostOk:self];
			
		
	} else {
		
		NSLog(@"cocoslive: Post Score failed. Reason: %@", dataString);

		// Error parsing answer
		postStatus_ = kPostStatusPostFailed;

		if( [delegate respondsToSelector:@selector(scorePostFail:) ] )
			[delegate scorePostFail:self];
	}
}

-(NSURLRequest *)connection:(NSURLConnection *)connection
			willSendRequest:(NSURLRequest *)request
           redirectResponse:(NSURLResponse *)redirectResponse
{
    NSURLRequest *newRequest=request;
    if (redirectResponse) {
        newRequest=nil;
    }
	
    return newRequest;
}

@end