Event Based programming problem

Discussion in 'Mac Programming' started by wlh99, Jul 17, 2011.

  1. wlh99 macrumors 6502

    Joined:
    Feb 7, 2008
    #1
    I’m working on a texas hold’em game. I have a method getEveryonesBet that goes through a round of betting, makes sure all the bets are equal, collects money, puts it in the pot. In that method I call:
    Code:
    –(float)getBetFromPlayer:(Player *)player 
    which asks a player for a bet and returns it. This worked fine in earlier versions of my program which were console based. Now that it is GUI based, and event based, execution stops while my program waits for getBetFromPlayer to return.
    I have “solved” the problem by running in a thread, but I know that isn’t the way to do it, and instead I need to convert to an event based program flow. I’m stuck and looking for ideas. Since getBetFromPlayer is nested in a couple loops, the event driven code would get very complicated any way I can think of.
    Here is getEveryonesBet:
    Code:
    -(void) getEveryonesBet {
        
        // get Everyone's initial bet
    	lastBet = 0;
    	currentBet = -1.0;
    
    	// while bets are not square (all the same) ask the next player for a bet.
    	int j = 0;
    	int oneRound = NO; // to insure at least one round of betting completes
    	while ( ( ![self betsAreSquare] ) || ( oneRound==NO )  ) { // while bets are not square (all the same) ask the next player for a bet.
    		
    	
            currentBet = [gameView getBetFromPlayer:[players objectAtIndex:j]];
    		while (currentBet < lastBet) {		// make sure bet is at least as high as previous bet
    			[gameView invalidBet:lastBet];
    			currentBet = [gameView getBetFromPlayer:[players objectAtIndex:j]];
    		}
    		
    		lastBet = currentBet;
    		
    		// update the money in the pot
    		pot += lastBet;
    		[gameView updatePot:pot];
    		
    		// subtract bet from player
    		Player *player = ((Player *)[players objectAtIndex:j]);
    		player.money -= lastBet;
    		if (player.money < 0) {
    			pot += player.money; // don't allow more  added to pot than player has
    			player.money = 0;
    			[gameView updatePot:pot];
    		}
    		[player display];
    
     		if ( (++j)==[players count]) {j = 0;oneRound=TRUE;} // loop back to player 0 until while loop is satisfied.       
    	} //while loop
    	
    } // get everyones bet
    
    
    
    The entire project is at code.google.com/wlhcards
     
  2. gnasher729 macrumors P6

    gnasher729

    Joined:
    Nov 25, 2005
    #2
    Can we start not with the code that you are writing, but how the application will be used? So I double-click your application. What would I see on the screen? What actions could I take? What would happen after each action?
     
  3. wlh99 thread starter macrumors 6502

    Joined:
    Feb 7, 2008
    #3
    I get what you are asking, but the determination of the action to take isn't a simple one-to-one relationship.

    I will need to have data members to keep track of what player is betting, and at what point in the game we are. I'll need to determine if the bet meets the minimum bet, if it is a raise then make other players bet again etc. It seems that what is handled pretty simply in the while loop I posted earlier gets messy fast.

    That said, I am roughing it out: (I write in comments first while I work out logic, then they become documentation later) And it isn't as bad as I suppose it could be.

    Code:
    // -(IBAction) gotBetFromPlayer (Player *) player
    // is bet from player we expect?
    		// if not throw error
    // is bet valid?
    		// if not throw error and rebet
    // bet is valid
    		// lastbet=currentbet
    		// subtract money from player
    		// update money in the pot
    		// gameView updatePot
    		// player display
    // have all players bet?
    		// if not advance to next player
    //are all bets square?
    		// if not advance to next player
    		//if yes call next of:
    				// deal 2 cards
    				// deal flop
    				// deal turn
    				// deal river
    				// determine winner
    
    
    That above code would replace the core game code which now is:

    Code:
    		[self deal2cards];
    		[self getEveryonesBet];
    		[self dealFlop];
    		[self getEveryonesBet];
    		[self dealTurn];
    		[self getEveryonesBet];
    		[self dealRiver];
    		[self getEveryonesBet];
    		[self determineWinner];
    
    
     
  4. robbieduncan Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #4
    You need to change anything where you are expecting user interaction from "active" to "passive". You need an internal data model that represents the interaction you are currently expecting (say player 1 is about to make a bet: this means all other players are expected to do nothing). Your even handler methods then transition your internal state between a series of well defined states (so in the event hander you transition player 1's state to the correct one for the bet or fold made and move the action to the next available plater and if any other player attempts to play out of turn you ignore that/beep). You don't have loops or methods that "get" input from the users.
     
  5. wlh99 thread starter macrumors 6502

    Joined:
    Feb 7, 2008
    #5
    It's working(more or less, still a few bugs), although it's ugly and very hard to follow. It's what I was trying to avoid.

    Code:
    -(void)gotBetFromPlayer:(Player *) player {
    	NSLog(@"gotBetFromPlayer");
    
    
    // is bet from player we expect?
    if (player != [players objectAtIndex:bettingPlayer]) {
    	// if not throw error
    
    	NSLog(@"Error! wrong player Bet!");
    	
    } else {
    	// is bet valid?
    	if (player.currentBet>=lastBet) {
    		currentBet = player.currentBet;
    		lastBet = currentBet;
    		
    		// subtract money from player
    		if ( lastBet < player.money ) { // dont put more money in pot than player has
    			player.money -= lastBet;
    			pot += lastBet;
    		} else {
    			pot += player.money;
    			player.money = 0;
    		}
    		[gameView updatePot:pot]; // display new pot amount	
    		[player display];	
    
    	
    		// have all players bet?
    		
    		if ((++bettingPlayer)==[players count]) {
    			// all players have bet
    			bettingPlayer = 0;
    			allPlayersBet = YES;
    		}
    		
    		if (allPlayersBet == YES) {
    			if ([self betsAreSquare]) { // if all bets are square
    				allPlayersBet = NO;
    				bettingPlayer = 0;
    				lastBet = -1.0;
    				switch (nextStep) {
    					case wDealFlop:
    						[self dealFlop];
    						[gameView getBetFromPlayer:[players objectAtIndex:bettingPlayer]];
    						nextStep++;
    						break;
    					case wDealTurn:
    						[self dealTurn];
    						[gameView getBetFromPlayer:[players objectAtIndex:bettingPlayer]];
    						nextStep++;
    						break;
    					case wDealRiver:
    						[self dealRiver];
    						[gameView getBetFromPlayer:[players objectAtIndex:bettingPlayer]];
    						nextStep++;
    						break;
    					case wDetermineWinner:
    						[self determineWinner];
    						[self endHand];
    						nextStep++;
    						break;
    					default:
    						break;
    				}
    				NSLog(@"nextStep = %d",nextStep);
    				
    				if (nextStep == wHandOver) { // case of end of Hand
    					
    					NSLog(@"End of Hand");
    					currentBet = -1.0;
    					lastBet = -1.0;
    					bettingPlayer = 0;
    					nextStep = wDeal2Cards;
    					[self deal2cards];
    					nextStep += 1;
    					[gameView getBetFromPlayer:[players objectAtIndex:0]];
    					
    				}
    		} // if all bets are square
    			
    	} // all players have bet
    		
    	[gameView getBetFromPlayer:[players objectAtIndex:bettingPlayer]];
    
    		
    		
    	} else { // valid bet
    		// this is not a valid bet
    		[gameView invalidBet:lastBet];
    }
     
    	
    	
    }
    
    	
    	
    	
    
    } // gotBetFromPlayer
    
    
     
  6. blueillusion macrumors member

    Joined:
    Aug 18, 2008
    #6
    I have a few suggestions to make.

    First of all at the top:

    Code:
    // is bet from player we expect?
    if (player != [players objectAtIndex:bettingPlayer]) {
    	// if not throw error
    
    	NSLog(@"Error! wrong player Bet!");
    	
    }
    Why not put a return; statement after the nslog? The only code that gets executed is your else statement if your condition fails.
    You can save your self a set of brackets and some indentation.

    And second of all, maybe you can separate the gotBetFromPlayer method's guts a bit more.

    I think you could make that method only deal with a players bet. Perhaps have another method to deal with checking if all players have bet. After all, your method name seems to only deal with one player only.
     

Share This Page