use a proper bundle identifier
authorkoda
Thu, 29 Apr 2010 02:43:28 +0000
changeset 3373 c1ff724a5c34
parent 3372 5d3daec0d0b5
child 3374 0d522416d97f
use a proper bundle identifier fix land preview add theme selection and map preview
cocoaTouch/GameConfigViewController.m
cocoaTouch/GameSetup.m
cocoaTouch/GravesViewController.m
cocoaTouch/MapConfigViewController.h
cocoaTouch/MapConfigViewController.m
cocoaTouch/TeamSettingsViewController.m
cocoaTouch/otherSrc/CommodityFunctions.h
cocoaTouch/otherSrc/CommodityFunctions.m
cocoaTouch/xib/MapConfigViewController-iPhone.xib
project_files/HedgewarsMobile/HedgewarsMobile.xcodeproj/project.pbxproj
share/Info.plist.in
--- a/cocoaTouch/GameConfigViewController.m	Wed Apr 28 05:58:14 2010 +0000
+++ b/cocoaTouch/GameConfigViewController.m	Thu Apr 29 02:43:28 2010 +0000
@@ -96,6 +96,7 @@
                                                                       mapConfigViewController.templateFilterCommand,@"templatefilter_command",
                                                                       mapConfigViewController.mapGenCommand,@"mapgen_command",
                                                                       mapConfigViewController.mazeSizeCommand,@"mazesize_command",
+                                                                      mapConfigViewController.themeCommand,@"theme_command",
                                                                       teamConfigViewController.listOfSelectedTeams,@"teams_list",nil];
     [dict writeToFile:GAMECONFIG_FILE() atomically:YES];
     [dict release];
@@ -120,6 +121,12 @@
     [super viewWillAppear:animated];
 }
 
+-(void) viewDidAppear:(BOOL)animated {
+    [mapConfigViewController viewDidAppear:animated];
+    [teamConfigViewController viewDidAppear:animated];
+    [super viewDidAppear:animated];
+}
+
 -(void) didReceiveMemoryWarning {
     // Releases the view if it doesn't have a superview.
     [super didReceiveMemoryWarning];
--- a/cocoaTouch/GameSetup.m	Wed Apr 28 05:58:14 2010 +0000
+++ b/cocoaTouch/GameSetup.m	Thu Apr 29 02:43:28 2010 +0000
@@ -24,10 +24,10 @@
 
 -(id) init {
 	if (self = [super init]) {
-    	srandom(time(NULL));
         ipcPort = randomPort();
         
-        NSDictionary *dictSett = [[NSDictionary alloc] initWithContentsOfFile:SETTINGS_FILE()]; //should check it exists
+        // should check they exist and throw and exection if not
+        NSDictionary *dictSett = [[NSDictionary alloc] initWithContentsOfFile:SETTINGS_FILE()];
         self.systemSettings = dictSett;
         [dictSett release];
         
@@ -50,11 +50,13 @@
 
 #pragma mark -
 #pragma mark Thread/Network relevant code
+// select one of GameSetup method and execute it in a seprate thread
 -(void) startThread: (NSString *) selector {
 	SEL usage = NSSelectorFromString(selector);
 	[NSThread detachNewThreadSelector:usage toTarget:self withObject:nil];
 }
 
+// wrapper that computes the length of the message and then sends the command string
 -(int) sendToEngine: (NSString *)string {
 	unsigned char length = [string length];
 	
@@ -62,6 +64,7 @@
 	return SDLNet_TCP_Send(csd, [string UTF8String], length);
 }
 
+// unpacks team data from the team.plist to a sequence of commands for engine
 -(void) sendTeamData:(NSString *)fileName withPlayingHogs:(NSInteger) playingHogs ofColor:(NSNumber *)color{    
     NSString *teamFile = [[NSString alloc] initWithFormat:@"%@/%@", TEAMS_DIRECTORY(), fileName];
     NSDictionary *teamData = [[NSDictionary alloc] initWithContentsOfFile:teamFile];
@@ -103,6 +106,7 @@
     [teamData release];
 }
 
+// unpacks ammodata from the ammo.plist to a sequence of commands for engine
 -(void) sendAmmoData:(NSDictionary *)ammoData forTeams: (NSInteger)numberPlaying {
     NSString *ammloadt = [[NSString alloc] initWithFormat:@"eammloadt %@", [ammoData objectForKey:@"ammostore_initialqt"]];
     [self sendToEngine: ammloadt];
@@ -127,6 +131,7 @@
     [ammstore release];
 }
 
+// method that handles net setup with engine and keeps connection alive
 -(void) engineProtocol {
 	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 	IPaddress ip;
@@ -143,13 +148,13 @@
         serverQuit = YES;
 	}
 	
-	/* Resolving the host using NULL make network interface to listen */
+	// Resolving the host using NULL make network interface to listen
 	if (SDLNet_ResolveHost(&ip, NULL, ipcPort) < 0) {
 		NSLog(@"SDLNet_ResolveHost: %s\n", SDLNet_GetError());
         serverQuit = YES;
 	}
 	
-	/* Open a connection with the IP provided (listen on the host's port) */
+	// Open a connection with the IP provided (listen on the host's port) 
 	if (!(sd = SDLNet_TCP_Open(&ip))) {
 		NSLog(@"SDLNet_TCP_Open: %s %\n", SDLNet_GetError(), ipcPort);
         serverQuit = YES;
@@ -158,18 +163,19 @@
 	NSLog(@"engineProtocol - Waiting for a client on port %d", ipcPort);
 	while (!serverQuit) {
 		
-		/* This check the sd if there is a pending connection.
-		 * If there is one, accept that, and open a new socket for communicating */
+		// This check the sd if there is a pending connection.
+        // If there is one, accept that, and open a new socket for communicating
 		csd = SDLNet_TCP_Accept(sd);
 		if (NULL != csd) {
-			
+			// Now we can communicate with the client using csd socket
+			// sd will remain opened waiting other connections
 			NSLog(@"engineProtocol - Client found");
 			
 			//first byte of the command alwayas contain the size of the command
 			SDLNet_TCP_Recv(csd, &msgSize, sizeof(Uint8));
 			
 			SDLNet_TCP_Recv(csd, buffer, msgSize);
-			gameTicks = SDLNet_Read16(&buffer[msgSize - 2]);
+			gameTicks = SDLNet_Read16 (&buffer[msgSize - 2]);
 			//NSLog(@"engineProtocol - %d: received [%s]", gameTicks, buffer);
 			
 			if ('C' == buffer[0]) {
@@ -189,28 +195,29 @@
 				[self sendToEngine:[self.gameConfig objectForKey:@"seed_command"]];
 				
 				// various flags
-				[self sendToEngine:@"e$gmflags 256"]; 
+				[self sendToEngine:@"e$gmflags 8448"]; 
 				[self sendToEngine:@"e$damagepct 100"];
 				[self sendToEngine:@"e$turntime 45000"];
 				[self sendToEngine:@"e$minestime 3000"];
 				[self sendToEngine:@"e$landadds 4"];
 				[self sendToEngine:@"e$sd_turns 15"];
 				[self sendToEngine:@"e$casefreq 5"];
+				[self sendToEngine:@"e$explosives 2"];
+				[self sendToEngine:@"e$minedudpct 0"];
 
 				// dimension of the map
 				[self sendToEngine:[self.gameConfig objectForKey:@"templatefilter_command"]];
 				[self sendToEngine:[self.gameConfig objectForKey:@"mapgen_command"]];
 				[self sendToEngine:[self.gameConfig objectForKey:@"mazesize_command"]];
-								
+
 				// theme info
-				[self sendToEngine:@"etheme Compost"];
+				[self sendToEngine:[self.gameConfig objectForKey:@"theme_command"]];
 				
                 NSArray *teamsConfig = [self.gameConfig objectForKey:@"teams_list"];
                 for (NSDictionary *teamData in teamsConfig) {
                     [self sendTeamData:[teamData objectForKey:@"team"] 
                        withPlayingHogs:[[teamData objectForKey:@"number"] intValue]
                                ofColor:[teamData objectForKey:@"color"]];
-                    NSLog(@"teamData sent");
                 }
                 
                 NSDictionary *ammoData = [[NSDictionary alloc] initWithObjectsAndKeys:
@@ -228,8 +235,6 @@
 			}
 			
 			while (!clientQuit){
-				/* Now we can communicate with the client using csd socket
-				 * sd will remain opened waiting other connections */
 				msgSize = 0;
 				memset(buffer, 0, BUFFER_SIZE);
 				memset(string, 0, BUFFER_SIZE);
@@ -300,6 +305,7 @@
 
 #pragma mark -
 #pragma mark Setting methods
+// returns an array of c-strings that are read by engine at startup
 -(const char **)getSettings {
 	NSString *ipcString = [[NSString alloc] initWithFormat:@"%d", ipcPort];
 	NSString *localeString = [[NSString alloc] initWithFormat:@"%@.txt", [[NSLocale currentLocale] objectForKey:NSLocaleLanguageCode]];
@@ -331,11 +337,10 @@
     // prevents using an empty nickname
     NSString *username;
     NSString *originalUsername = [self.systemSettings objectForKey:@"username"];
-    if ([originalUsername length] == 0) {
+    if ([originalUsername length] == 0)
         username = [[NSString alloc] initWithFormat:@"MobileUser-%@",ipcString];
-    } else {
+    else
         username = [[NSString alloc] initWithString:originalUsername];
-    }
     
 	gameArgs[0] = [username UTF8String];                                                        //UserNick
 	gameArgs[1] = [ipcString UTF8String];                                                       //ipcPort
--- a/cocoaTouch/GravesViewController.m	Wed Apr 28 05:58:14 2010 +0000
+++ b/cocoaTouch/GravesViewController.m	Thu Apr 29 02:43:28 2010 +0000
@@ -82,9 +82,8 @@
     static NSString *CellIdentifier = @"Cell";
     
     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
-    if (cell == nil) {
+    if (cell == nil)
         cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
-    }
     
     NSString *grave = [[graveArray objectAtIndex:[indexPath row]] stringByDeletingPathExtension];
     cell.textLabel.text = grave;
--- a/cocoaTouch/MapConfigViewController.h	Wed Apr 28 05:58:14 2010 +0000
+++ b/cocoaTouch/MapConfigViewController.h	Thu Apr 29 02:43:28 2010 +0000
@@ -12,13 +12,17 @@
 @interface MapConfigViewController : UIViewController <UITableViewDelegate, UITableViewDataSource> {
     TCPsocket sd, csd;
     unsigned char map[128*32];
-
+    NSInteger oldValue;  //slider
+    NSInteger oldPage;   //segmented control
+    BOOL busy;
+    
     // objects read (mostly) by parent view
     NSInteger maxHogs;
     NSString *seedCommand;
     NSString *templateFilterCommand;
     NSString *mapGenCommand;
     NSString *mazeSizeCommand;
+    NSString *themeCommand;
    
     // various widgets in the view
     UIButton *previewButton;
@@ -27,6 +31,11 @@
     UILabel *sizeLabel;
     UISegmentedControl *segmentedControl;
     UISlider *slider;
+    
+    // internal objects
+    NSIndexPath *lastIndexPath;
+    NSArray *themeArray;
+    NSArray *mapArray;
 }
 
 @property (nonatomic) NSInteger maxHogs;
@@ -34,6 +43,8 @@
 @property (nonatomic,retain) NSString *templateFilterCommand;
 @property (nonatomic,retain) NSString *mapGenCommand;
 @property (nonatomic,retain) NSString *mazeSizeCommand;
+@property (nonatomic,retain) NSString *themeCommand;
+
 @property (nonatomic,retain) IBOutlet UIButton *previewButton;
 @property (nonatomic,retain) IBOutlet UITableView *tableView;
 @property (nonatomic,retain) IBOutlet UILabel *maxLabel;
@@ -41,10 +52,16 @@
 @property (nonatomic,retain) IBOutlet UISegmentedControl *segmentedControl;
 @property (nonatomic,retain) IBOutlet UISlider *slider;
 
+@property (nonatomic,retain) NSIndexPath *lastIndexPath;
+@property (nonatomic,retain) NSArray *themeArray;
+@property (nonatomic,retain) NSArray *mapArray;
+
 -(IBAction) updatePreview;
 -(IBAction) sliderChanged:(id) sender;
 -(IBAction) sliderEndedChanging:(id) sender;
 -(IBAction) segmentedControlChanged:(id) sender;
+-(void) turnOnWidgets;
+-(void) turnOffWidgets;
 
 -(void) engineProtocol:(NSInteger) port;
 
--- a/cocoaTouch/MapConfigViewController.m	Wed Apr 28 05:58:14 2010 +0000
+++ b/cocoaTouch/MapConfigViewController.m	Thu Apr 29 02:43:28 2010 +0000
@@ -14,10 +14,10 @@
 #import <pthread.h>
 
 #define INDICATOR_TAG 7654
-#define RANDOMSTR_LEN 36
+
 @implementation MapConfigViewController
-@synthesize previewButton, maxHogs, seedCommand, templateFilterCommand, mapGenCommand, mazeSizeCommand,
-            tableView, maxLabel, sizeLabel, segmentedControl, slider;
+@synthesize previewButton, maxHogs, seedCommand, templateFilterCommand, mapGenCommand, mazeSizeCommand, themeCommand,
+            tableView, maxLabel, sizeLabel, segmentedControl, slider, lastIndexPath, themeArray, mapArray;
 
 
 -(BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
@@ -44,13 +44,13 @@
         serverQuit = YES;
 	}
 	
-	/* Resolving the host using NULL make network interface to listen */
+	// Resolving the host using NULL make network interface to listen
 	if (SDLNet_ResolveHost(&ip, NULL, port) < 0) {
 		NSLog(@"SDLNet_ResolveHost: %s\n", SDLNet_GetError());
         serverQuit = YES;
 	}
 	
-	/* Open a connection with the IP provided (listen on the host's port) */
+	// Open a connection with the IP provided (listen on the host's port)
 	if (!(sd = SDLNet_TCP_Open(&ip))) {
 		NSLog(@"SDLNet_TCP_Open: %s %\n", SDLNet_GetError(), port);
         serverQuit = YES;
@@ -101,26 +101,23 @@
     for (int i = 0; i < 32*128; i++) {
         unsigned char byte = map[i];
         for (int j = 0; j < 8; j++) {
-            // select the color based on the rightmost bit
-            if ((byte & 0x00000001) != 0)
+            // select the color based on the leftmost bit
+            if ((byte & 0x80) != 0)
                 CGContextSetRGBFillColor(context, 0.5, 0.5, 0.7, 1.0);
             else
                 CGContextSetRGBFillColor(context, 0.0, 0.0, 0.0, 0.0);
-            
             // draw pixel
             CGContextFillRect(context,CGRectMake(xc,yc,1,1));
             // move coordinates
             xc = (xc + 1) % 256;
             if (xc == 0) yc++;
-            
             // shift to next bit
-            byte = byte >> 1;
+            byte <<= 1;
         }
     }
     UIGraphicsPopContext();
     UIImage *previewImage = UIGraphicsGetImageFromCurrentImageContext();
     UIGraphicsEndImageContext();
-    
 
     // set the preview image (autoreleased) in the button and the maxhog label
     [self.previewButton setBackgroundImage:previewImage forState:UIControlStateNormal];
@@ -147,7 +144,76 @@
     */
 }
 
+-(IBAction) updatePreview {
+    // don't generate a new preview while it's already generating one
+    if (busy)
+        return;
+    
+    // generate a seed
+    CFUUIDRef uuid = CFUUIDCreate(kCFAllocatorDefault);
+    NSString *seed = (NSString *)CFUUIDCreateString(kCFAllocatorDefault, uuid);
+    CFRelease(uuid);
+    NSString *seedCmd = [[NSString alloc] initWithFormat:@"eseed {%@}", seed];
+    [seed release];
+    self.seedCommand = seedCmd;
+    [seedCmd release];
+    
+    NSIndexPath *theIndex;
+    if (segmentedControl.selectedSegmentIndex != 1) {
+        // prevent other events and add an activity while the preview is beign generated
+        [self turnOffWidgets];
+        
+        // remove the current preview
+        [self.previewButton setImage:nil forState:UIControlStateNormal];
+        
+        // add a very nice spinning wheel
+        UIActivityIndicatorView *indicator = [[UIActivityIndicatorView alloc] 
+                                              initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
+        indicator.center = CGPointMake(previewButton.bounds.size.width / 2, previewButton.bounds.size.height / 2);
+        indicator.tag = INDICATOR_TAG;
+        [indicator startAnimating];
+        [self.previewButton addSubview:indicator];
+        [indicator release];
+        
+        // let's draw in a separate thread so the gui can work; at the end it restore other widgets
+        [NSThread detachNewThreadSelector:@selector(drawingThread) toTarget:self withObject:nil];
+    
+        theIndex = [NSIndexPath indexPathForRow:(random()%[self.themeArray count]) inSection:0];
+    } else {
+        theIndex = [NSIndexPath indexPathForRow:(random()%[self.mapArray count]) inSection:0];
+    }
+    [self.tableView reloadData];
+    [self tableView:self.tableView didSelectRowAtIndexPath:theIndex];
+    [self.tableView scrollToRowAtIndexPath:theIndex atScrollPosition:UITableViewScrollPositionNone animated:YES];
+}
+
+-(void) updatePreviewWithMap:(NSInteger) index {
+    // change the preview button
+    NSString *fileImage = [[NSString alloc] initWithFormat:@"%@/%@/preview.png", MAPS_DIRECTORY(),[self.mapArray objectAtIndex:index]];
+    UIImage *image = [[UIImage alloc] initWithContentsOfFile:fileImage];
+    [fileImage release];
+    [self.previewButton setBackgroundImage:image forState:UIControlStateNormal];
+    [image release];
+    
+    // update label
+    maxHogs = 18;
+    NSString *fileCfg = [[NSString alloc] initWithFormat:@"%@/%@/map.cfg", MAPS_DIRECTORY(),[self.mapArray objectAtIndex:index]];
+    NSString *contents = [[NSString alloc] initWithContentsOfFile:fileCfg encoding:NSUTF8StringEncoding error:NULL];
+    [fileCfg release];
+    NSArray *split = [contents componentsSeparatedByString:@"\n"];
+
+    // if the number is not set we keep 18 standard; 
+    // sometimes it's not set but there are trailing characters, we get around them with the second equation
+    if ([split count] > 1 && [[split objectAtIndex:1] intValue] > 0)
+        maxHogs = [[split objectAtIndex:1] intValue];
+    [contents release];
+    NSString *max = [[NSString alloc] initWithFormat:@"%d",maxHogs];
+    self.maxLabel.text = max;
+    [max release];
+}
+
 -(void) turnOffWidgets {
+    busy = YES;
     self.previewButton.alpha = 0.5f;
     self.previewButton.enabled = NO;
     self.maxLabel.text = @"...";
@@ -162,72 +228,84 @@
     self.segmentedControl.enabled = YES;
     self.tableView.allowsSelection = YES;
     self.slider.enabled = YES;
+    busy = NO;
 }
-
--(IBAction) updatePreview {
-    // prevent other events and add an activity while the preview is beign generated
-    [self turnOffWidgets];
-    
-    // remove the current preview
-    [self.previewButton setImage:nil forState:UIControlStateNormal];
     
-    // add a very nice spinning wheel
-    UIActivityIndicatorView *indicator = [[UIActivityIndicatorView alloc] 
-                                          initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
-    indicator.center = CGPointMake(previewButton.bounds.size.width / 2, previewButton.bounds.size.height / 2);
-    indicator.tag = INDICATOR_TAG;
-    [indicator startAnimating];
-    [self.previewButton addSubview:indicator];
-    [indicator release];
-
-    // generate a seed
-    char randomStr[RANDOMSTR_LEN+1];
-    for (int i = 0; i < RANDOMSTR_LEN; ) {
-        randomStr[i] = random() % 255;
-        if (randomStr[i] >= '0' && randomStr[i] <= '9' || randomStr[i] >= 'a' && randomStr[i] <= 'z') 
-            i++;
-    }
-    randomStr[ 8] = '-';
-    randomStr[13] = '-';
-    randomStr[18] = '-';
-    randomStr[23] = '-';
-    randomStr[RANDOMSTR_LEN] = '\0';
-    NSString *seedCmd = [[NSString alloc] initWithFormat:@"eseed {%s}", randomStr];
-    self.seedCommand = seedCmd;
-    [seedCmd release];
-    
-    // let's draw in a separate thread so the gui can work; also it restores the preview button
-    [NSThread detachNewThreadSelector:@selector(drawingThread) toTarget:self withObject:nil];
-}
-
 #pragma mark -
 #pragma mark Table view data source
 -(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView {
     return 1;
 }
 
--(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
-    return 1;
+-(NSInteger) tableView:(UITableView *)aTableView numberOfRowsInSection:(NSInteger) section {
+    if (self.segmentedControl.selectedSegmentIndex != 1)
+        return [themeArray count];
+    else
+        return [mapArray count];
 }
 
 -(UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
     static NSString *CellIdentifier = @"Cell";
+    NSInteger row = [indexPath row];
     
     UITableViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:CellIdentifier];
     if (cell == nil) 
         cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
     
+    if (self.segmentedControl.selectedSegmentIndex != 1) {
+        // the % prevents a strange bug that occurs sporadically
+        NSString *themeName = [self.themeArray objectAtIndex:row % [self.themeArray count]];
+        cell.textLabel.text = themeName;
+        UIImage *image = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"%@/%@/Icon.png",THEMES_DIRECTORY(),themeName]];
+        cell.imageView.image = [image scaleToSize:CGSizeMake(40, 40)];
+    } else {
+        cell.textLabel.text = [self.mapArray objectAtIndex:row];
+        cell.imageView.image = nil;
+    }
+    
+    if (row == [self.lastIndexPath row]) 
+        cell.accessoryType = UITableViewCellAccessoryCheckmark;
+    else
+        cell.accessoryType = UITableViewCellAccessoryNone;
+
     return cell;
 }
 
+
+#pragma mark -
+#pragma mark Table view delegate
+-(void) tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
+    int newRow = [indexPath row];
+    int oldRow = (lastIndexPath != nil) ? [lastIndexPath row] : -1;
+    
+    if (newRow != oldRow) {
+        if (self.segmentedControl.selectedSegmentIndex != 1) {
+            NSString *theme = [self.themeArray objectAtIndex:newRow];
+            self.themeCommand =  [NSString stringWithFormat:@"etheme %@", theme];
+        } else
+            [self updatePreviewWithMap:newRow];
+
+        UITableViewCell *newCell = [aTableView cellForRowAtIndexPath:indexPath]; 
+        newCell.accessoryType = UITableViewCellAccessoryCheckmark;
+        UITableViewCell *oldCell = [aTableView cellForRowAtIndexPath:self.lastIndexPath];
+        oldCell.accessoryType = UITableViewCellAccessoryNone;
+
+        self.lastIndexPath = indexPath;
+        [aTableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionNone];
+    }
+    [aTableView deselectRowAtIndexPath:indexPath animated:YES];
+}
+
 #pragma mark -
 #pragma mark slider & segmentedControl
+// this updates the label and the command keys when the slider is moved, depending of the selection in segmentedControl
+// no methods are called by this routine and you can pass nil to it
 -(IBAction) sliderChanged:(id) sender {
     NSString *labelText;
     NSString *templateCommand;
     NSString *mazeCommand;
     
-    switch ((int)(slider.value*100)) {
+    switch ((int)(self.slider.value*100)) {
         case 0:
             if (self.segmentedControl.selectedSegmentIndex == 0) {
                 labelText = NSLocalizedString(@"Wacky",@"");
@@ -285,84 +363,135 @@
         default:
             break;
     }
+    
     self.sizeLabel.text = labelText;
     self.templateFilterCommand = templateCommand;
     self.mazeSizeCommand = mazeCommand;
 }
 
-// update preview as soon as the user lifts its finger
+// update preview (if not busy and if its value really changed) as soon as the user lifts its finger up
 -(IBAction) sliderEndedChanging:(id) sender {
-    if (self.previewButton.enabled == YES)
+    int num = (int) (self.slider.value * 100);
+    if (oldValue != num) {
         [self updatePreview];
+        oldValue = num;
+    }
 }
 
+// perform actions based on the activated section, then call updatePreview to visually update the selection 
+// updatePreview will call didSelectRowAtIndexPath which will call the right update routine)
+// and if necessary update the table with a slide animation
 -(IBAction) segmentedControlChanged:(id) sender {
     NSString *mapgen;
+    NSInteger newPage = self.segmentedControl.selectedSegmentIndex;
     
-    switch (segmentedControl.selectedSegmentIndex) {
+    switch (newPage) {
         case 0: // Random
             mapgen = @"e$mapgen 0";
             [self sliderChanged:nil];
-            if (self.previewButton.enabled == YES)
-                [self updatePreview];
+            self.slider.enabled = YES;
             break;
+            
         case 1: // Map
             mapgen = @"e$mapgen 0";
-            // other stuff
+            self.slider.enabled = NO;
+            self.sizeLabel.text = @".";
             break;
+            
         case 2: // Maze
             mapgen = @"e$mapgen 1";
             [self sliderChanged:nil];
-            if (self.previewButton.enabled == YES)
-                [self updatePreview];
-
+            self.slider.enabled = YES;
             break;
     }
     self.mapGenCommand = mapgen;
+    [self updatePreview];
+    
+    // nice animation for updating the table when needed
+    if (((oldPage == 0 || oldPage == 2) && newPage == 1) ||
+        (oldPage == 1 && (newPage == 0 || newPage == 2))) {
+        [UIView beginAnimations:@"moving out table" context:NULL];
+        self.tableView.frame = CGRectMake(480, 0, 185, 276);
+        [UIView commitAnimations];
+        [self performSelector:@selector(moveTable) withObject:nil afterDelay:0.2];
+    }
+    oldPage = newPage;
+}
+
+// update data when table is not visible and then show it
+-(void) moveTable {
+    [self.tableView reloadData];
+    
+    [UIView beginAnimations:@"moving in table" context:NULL];
+    self.tableView.frame = CGRectMake(295, 0, 185, 276);
+    [UIView commitAnimations];
 }
 
 #pragma mark -
 #pragma mark view management
 -(void) viewDidLoad {
-    srandom(time(NULL));
     [super viewDidLoad];
 
     CGSize screenSize = [[UIScreen mainScreen] bounds].size;
     self.view.frame = CGRectMake(0, 0, screenSize.height, screenSize.width - 44);
 
+    // themes.cfg contains all the user-selectable themes
+    NSString *string = [[NSString alloc] initWithContentsOfFile:[THEMES_DIRECTORY() stringByAppendingString:@"/themes.cfg"]
+                                                       encoding:NSUTF8StringEncoding 
+                                                          error:NULL];
+    NSMutableArray *array = [[NSMutableArray alloc] initWithArray:[string componentsSeparatedByString:@"\n"]];
+    [string release];
+    // remove a trailing "" element
+    [array removeLastObject];
+    self.themeArray = array;
+    [array release];
+    self.mapArray = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:MAPS_DIRECTORY() error:NULL];
+
+    self.tableView.rowHeight = 42;
+    busy = NO;
+    // initialize some "default" values
     self.sizeLabel.text = NSLocalizedString(@"All",@"");
+    self.slider.value = 0.05f;
+    self.segmentedControl.selectedSegmentIndex = 0;
+
     self.templateFilterCommand = @"e$template_filter 0";
-    self.segmentedControl.selectedSegmentIndex == 0;
     self.mazeSizeCommand = @"e$maze_size 0";
     self.mapGenCommand = @"e$mapgen 0";
+    
+    oldValue = 5;
+    oldPage = 0;
 }
 
--(void) viewWillAppear:(BOOL)animated {
-    [super viewWillAppear:animated];
+-(void) viewDidAppear:(BOOL) animated {
+    [super viewDidAppear:animated];
     [self updatePreview];
 }
 
--(void) didReceiveMemoryWarning {
-    // Releases the view if it doesn't have a superview.
-    [super didReceiveMemoryWarning];
-    // Release any cached data, images, etc that aren't in use.
-}
-
 #pragma mark -
 #pragma mark memory
+-(void) didReceiveMemoryWarning {
+    [super didReceiveMemoryWarning];
+}
+
 -(void) viewDidUnload {
     self.previewButton = nil;
     self.seedCommand = nil;
-    self.seedCommand = nil;
     self.templateFilterCommand = nil;
     self.mapGenCommand = nil;
     self.mazeSizeCommand = nil;
+    self.themeCommand = nil;
+    
     self.previewButton = nil;
     self.tableView = nil;
     self.maxLabel = nil;
     self.sizeLabel = nil;
     self.segmentedControl = nil;
     self.slider = nil;
+    
+    self.lastIndexPath = nil;
+    self.themeArray = nil;
+    self.mapArray = nil;
+    
     [super viewDidUnload];
 }
 
@@ -371,12 +500,19 @@
     [templateFilterCommand release];
     [mapGenCommand release];
     [mazeSizeCommand release];
+    [themeCommand release];
+    
     [previewButton release];
     [tableView release];
     [maxLabel release];
     [sizeLabel release];
     [segmentedControl release];
     [slider release];
+    
+    [lastIndexPath release];
+    [themeArray release];
+    [mapArray release];
+    
     [super dealloc];
 }
 
--- a/cocoaTouch/TeamSettingsViewController.m	Wed Apr 28 05:58:14 2010 +0000
+++ b/cocoaTouch/TeamSettingsViewController.m	Thu Apr 29 02:43:28 2010 +0000
@@ -43,7 +43,6 @@
     [array release];
     
     [self.tableView reloadData];
-    NSLog(@"files: %@", self.listOfTeams);
 }
 
 // modifies the navigation bar to add the "Add" and "Done" buttons
--- a/cocoaTouch/otherSrc/CommodityFunctions.h	Wed Apr 28 05:58:14 2010 +0000
+++ b/cocoaTouch/otherSrc/CommodityFunctions.h	Thu Apr 29 02:43:28 2010 +0000
@@ -23,10 +23,14 @@
 #define HATS_DIRECTORY()        [[[NSBundle mainBundle] resourcePath] stringByAppendingString:@"/Data/Graphics/Hats/"]
 #define GRAVES_DIRECTORY()      [[[NSBundle mainBundle] resourcePath] stringByAppendingString:@"/Data/Graphics/Graves/"]
 #define BOTLEVELS_DIRECTORY()   [[[NSBundle mainBundle] resourcePath] stringByAppendingString:@"/Data/Graphics/Hedgehog/botlevels"]
+#define FLAGS_DIRECTORY()       [[[NSBundle mainBundle] resourcePath] stringByAppendingString:@"/Data/Graphics/Flags/"]
 #define FORTS_DIRECTORY()       [[[NSBundle mainBundle] resourcePath] stringByAppendingString:@"/Data/Forts/"]
+#define THEMES_DIRECTORY()      [[[NSBundle mainBundle] resourcePath] stringByAppendingString:@"/Data/Themes/"]
+#define MAPS_DIRECTORY()        [[[NSBundle mainBundle] resourcePath] stringByAppendingString:@"/Data/Maps/"]
 #define VOICES_DIRECTORY()      [[[NSBundle mainBundle] resourcePath] stringByAppendingString:@"/Data/Sounds/voices/"]
-#define FLAGS_DIRECTORY()       [[[NSBundle mainBundle] resourcePath] stringByAppendingString:@"/Data/Graphics/Flags/"]
 
 void createTeamNamed (NSString *nameWithoutExt);
 BOOL rotationManager (UIInterfaceOrientation interfaceOrientation);
-NSInteger randomPort();
+NSInteger randomPort ();
+void popError (const char *title, const char *message);
+
--- a/cocoaTouch/otherSrc/CommodityFunctions.m	Wed Apr 28 05:58:14 2010 +0000
+++ b/cocoaTouch/otherSrc/CommodityFunctions.m	Thu Apr 29 02:43:28 2010 +0000
@@ -50,8 +50,20 @@
 
 }
 
-NSInteger randomPort() {
-    return (random() % 64541) + 1025;
+NSInteger randomPort () {
+    srandom(time(NULL));
+    return (random() % 64511) + 1024;
 }
 
+void popError (const char *title, const char *message) {
+    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:[NSString stringWithUTF8String:title]
+                                                    message:[NSString stringWithUTF8String:message]
+                                                   delegate:nil
+                                          cancelButtonTitle:@"Ok"
+                                          otherButtonTitles:nil];
+    [alert show];
+    [alert release];
+}
+    
 
+
--- a/cocoaTouch/xib/MapConfigViewController-iPhone.xib	Wed Apr 28 05:58:14 2010 +0000
+++ b/cocoaTouch/xib/MapConfigViewController-iPhone.xib	Thu Apr 29 02:43:28 2010 +0000
@@ -123,22 +123,6 @@
 							<bytes key="NSWhite">MC41AA</bytes>
 						</object>
 					</object>
-					<object class="IBUITableView" id="565214171">
-						<reference key="NSNextResponder" ref="191373211"/>
-						<int key="NSvFlags">274</int>
-						<string key="NSFrame">{{295, 0}, {185, 276}}</string>
-						<reference key="NSSuperview" ref="191373211"/>
-						<reference key="IBUIBackgroundColor" ref="437070330"/>
-						<bool key="IBUIClipsSubviews">YES</bool>
-						<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
-						<bool key="IBUIBouncesZoom">NO</bool>
-						<int key="IBUISeparatorStyle">1</int>
-						<int key="IBUISectionIndexMinimumDisplayRowCount">0</int>
-						<bool key="IBUIShowsSelectionImmediatelyOnTouchBegin">YES</bool>
-						<float key="IBUIRowHeight">44</float>
-						<float key="IBUISectionHeaderHeight">22</float>
-						<float key="IBUISectionFooterHeight">22</float>
-					</object>
 					<object class="IBUILabel" id="634417433">
 						<reference key="NSNextResponder" ref="191373211"/>
 						<int key="NSvFlags">292</int>
@@ -181,6 +165,22 @@
 						<float key="IBUIMinimumFontSize">10</float>
 						<int key="IBUITextAlignment">1</int>
 					</object>
+					<object class="IBUITableView" id="565214171">
+						<reference key="NSNextResponder" ref="191373211"/>
+						<int key="NSvFlags">274</int>
+						<string key="NSFrame">{{295, 0}, {185, 276}}</string>
+						<reference key="NSSuperview" ref="191373211"/>
+						<reference key="IBUIBackgroundColor" ref="437070330"/>
+						<bool key="IBUIClipsSubviews">YES</bool>
+						<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
+						<bool key="IBUIBouncesZoom">NO</bool>
+						<int key="IBUISeparatorStyle">1</int>
+						<int key="IBUISectionIndexMinimumDisplayRowCount">0</int>
+						<bool key="IBUIShowsSelectionImmediatelyOnTouchBegin">YES</bool>
+						<float key="IBUIRowHeight">44</float>
+						<float key="IBUISectionHeaderHeight">22</float>
+						<float key="IBUISectionFooterHeight">22</float>
+					</object>
 				</object>
 				<string key="NSFrameSize">{480, 276}</string>
 				<reference key="NSSuperview"/>
@@ -222,22 +222,6 @@
 				</object>
 				<object class="IBConnectionRecord">
 					<object class="IBCocoaTouchOutletConnection" key="connection">
-						<string key="label">dataSource</string>
-						<reference key="source" ref="565214171"/>
-						<reference key="destination" ref="372490531"/>
-					</object>
-					<int key="connectionID">14</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBCocoaTouchOutletConnection" key="connection">
-						<string key="label">delegate</string>
-						<reference key="source" ref="565214171"/>
-						<reference key="destination" ref="372490531"/>
-					</object>
-					<int key="connectionID">15</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBCocoaTouchOutletConnection" key="connection">
 						<string key="label">maxLabel</string>
 						<reference key="source" ref="372490531"/>
 						<reference key="destination" ref="634417433"/>
@@ -295,6 +279,30 @@
 					</object>
 					<int key="connectionID">23</int>
 				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBCocoaTouchOutletConnection" key="connection">
+						<string key="label">dataSource</string>
+						<reference key="source" ref="565214171"/>
+						<reference key="destination" ref="372490531"/>
+					</object>
+					<int key="connectionID">26</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBCocoaTouchOutletConnection" key="connection">
+						<string key="label">delegate</string>
+						<reference key="source" ref="565214171"/>
+						<reference key="destination" ref="372490531"/>
+					</object>
+					<int key="connectionID">27</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBCocoaTouchOutletConnection" key="connection">
+						<string key="label">tableView</string>
+						<reference key="source" ref="372490531"/>
+						<reference key="destination" ref="565214171"/>
+					</object>
+					<int key="connectionID">32</int>
+				</object>
 			</object>
 			<object class="IBMutableOrderedSet" key="objectRecords">
 				<object class="NSArray" key="orderedObjects">
@@ -311,11 +319,11 @@
 						<object class="NSMutableArray" key="children">
 							<bool key="EncodedWithXMLCoder">YES</bool>
 							<reference ref="326163764"/>
-							<reference ref="565214171"/>
 							<reference ref="634417433"/>
 							<reference ref="88728219"/>
 							<reference ref="938256702"/>
 							<reference ref="743202682"/>
+							<reference ref="565214171"/>
 						</object>
 						<reference key="parent" ref="0"/>
 					</object>
@@ -346,11 +354,6 @@
 						<reference key="parent" ref="191373211"/>
 					</object>
 					<object class="IBObjectRecord">
-						<int key="objectID">10</int>
-						<reference key="object" ref="565214171"/>
-						<reference key="parent" ref="191373211"/>
-					</object>
-					<object class="IBObjectRecord">
 						<int key="objectID">11</int>
 						<reference key="object" ref="634417433"/>
 						<reference key="parent" ref="191373211"/>
@@ -360,6 +363,12 @@
 						<reference key="object" ref="743202682"/>
 						<reference key="parent" ref="191373211"/>
 					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">25</int>
+						<reference key="object" ref="565214171"/>
+						<reference key="parent" ref="191373211"/>
+						<string key="objectName">Table View (Themes)</string>
+					</object>
 				</object>
 			</object>
 			<object class="NSMutableDictionary" key="flattenedProperties">
@@ -370,9 +379,9 @@
 					<string>-2.CustomClassName</string>
 					<string>1.IBEditorWindowLastContentRect</string>
 					<string>1.IBPluginDependency</string>
-					<string>10.IBPluginDependency</string>
 					<string>11.IBPluginDependency</string>
 					<string>17.IBPluginDependency</string>
+					<string>25.IBPluginDependency</string>
 					<string>7.IBPluginDependency</string>
 					<string>8.IBPluginDependency</string>
 					<string>9.IBPluginDependency</string>
@@ -407,7 +416,7 @@
 				</object>
 			</object>
 			<nil key="sourceID"/>
-			<int key="maxID">23</int>
+			<int key="maxID">32</int>
 		</object>
 		<object class="IBClassDescriber" key="IBDocument.Classes">
 			<object class="NSMutableArray" key="referencedPartialClassDescriptions">
@@ -442,6 +451,7 @@
 							<string>sizeLabel</string>
 							<string>slider</string>
 							<string>tableView</string>
+							<string>viewForTables</string>
 						</object>
 						<object class="NSMutableArray" key="dict.values">
 							<bool key="EncodedWithXMLCoder">YES</bool>
@@ -451,6 +461,7 @@
 							<string>UILabel</string>
 							<string>UISlider</string>
 							<string>UITableView</string>
+							<string>UIView</string>
 						</object>
 					</object>
 					<object class="IBClassDescriptionSource" key="sourceIdentifier">
--- a/project_files/HedgewarsMobile/HedgewarsMobile.xcodeproj/project.pbxproj	Wed Apr 28 05:58:14 2010 +0000
+++ b/project_files/HedgewarsMobile/HedgewarsMobile.xcodeproj/project.pbxproj	Thu Apr 29 02:43:28 2010 +0000
@@ -993,7 +993,7 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
-			shellScript = "#copy new stuff over old stuff\nrm -rf ${PROJECT_DIR}/Data\nsvn export --force ${PROJECT_DIR}/../../share/hedgewars/Data ${PROJECT_DIR}/Data\ncp -R ${PROJECT_DIR}/../../QTfrontend/res/botlevels ${PROJECT_DIR}/Data/Graphics/Hedgehog/botlevels\nrm -rf ${PROJECT_DIR}/Data/Graphics/Hedgehog/botlevels/.svn*\n\n#delete all CMakeLists.txt and image source files\nfind ${PROJECT_DIR}/Data -name CMakeLists.txt -delete\nfind ${PROJECT_DIR}/Data -name *.svg -delete\nfind ${PROJECT_DIR}/Data -name *.sifz -delete\nfind ${PROJECT_DIR}/Data -name *.xcf -delete\n\n#delete desktop frontend translation\nrm -rf ${PROJECT_DIR}/Data/Locale/hedgewars_*\n\n#the following ones must be removed when their support is implemented\n\n#delete some voices\nrm -rf ${PROJECT_DIR}/Data/Sounds/voices/{Classic,British,Mobster,Pirate,Robot,Russian,Singer,Surfer}\n\n#delete all names\nrm -rf ${PROJECT_DIR}/Data/Names/\n\n#delete all missions\nrm -rf ${PROJECT_DIR}/Data/Missions/\n\n#delete all reserved hats\nrm -rf ${PROJECT_DIR}/Data/Graphics/Hats/Reserved/";
+			shellScript = "#copy new stuff over old stuff\nrm -rf ${PROJECT_DIR}/Data\nsvn export --force ${PROJECT_DIR}/../../share/hedgewars/Data ${PROJECT_DIR}/Data\ncp -R ${PROJECT_DIR}/../../QTfrontend/res/botlevels ${PROJECT_DIR}/Data/Graphics/Hedgehog/botlevels\nrm -rf ${PROJECT_DIR}/Data/Graphics/Hedgehog/botlevels/.svn*\n\n#delete all CMakeLists.txt and image source files\nfind ${PROJECT_DIR}/Data -name CMakeLists.txt -delete\nfind ${PROJECT_DIR}/Data -name *.svg -delete\nfind ${PROJECT_DIR}/Data -name *.sifz -delete\nfind ${PROJECT_DIR}/Data -name *.xcf -delete\n\n#delete desktop frontend translation\nrm -rf ${PROJECT_DIR}/Data/Locale/hedgewars_*\n\n#delete dummy maps\nrm -rf ${PROJECT_DIR}/Data/Maps/{test*,KnockBall,Ruler,BasketBall}\n\n#the following ones must be removed when their support is implemented\n\n#delete some voices\nrm -rf ${PROJECT_DIR}/Data/Sounds/voices/{Classic,British,Mobster,Pirate,Robot,Russian,Singer,Surfer}\n\n#delete all names\nrm -rf ${PROJECT_DIR}/Data/Names/\n\n#delete all missions\nrm -rf ${PROJECT_DIR}/Data/Missions/\n\n#delete all reserved hats\nrm -rf ${PROJECT_DIR}/Data/Graphics/Hats/Reserved/";
 			showEnvVarsInLog = 0;
 		};
 		9283011B0F10CB2D00CC5A3C /* Build libfpc.a */ = {
--- a/share/Info.plist.in	Wed Apr 28 05:58:14 2010 +0000
+++ b/share/Info.plist.in	Thu Apr 29 02:43:28 2010 +0000
@@ -11,7 +11,7 @@
 	<key>CFBundleIconFile</key>
 	<string>Icon.icns</string>
 	<key>CFBundleIdentifier</key>
-	<string>com.hedgewars</string>
+	<string>org.hedgewars.desktop</string>
 	<key>CFBundlePackageType</key>
 	<string>APPL</string>
 	<key>CFBundleSignature</key>