 									   int *device_possible_lines, symbol_weight_t *device_symbols_weights, payout_t *device_payouts, double *device_expected_values, int *device_payout_frequencies) {
     int a_index = threadIdx.x;
     int b_index = blockIdx.x;
-    if (a_index < num_symbols_per_reel && b_index < num_symbols_per_reel) {
-       int device_index = a_index * num_symbols_per_reel + b_index;
-       device_payout_frequencies[device_index] = 0;
-       int i;
-       for(i=0;i < NUM_LINES; i++) {
-           int index = (device_index * NUM_LINES) + i;
-	   device_expected_values[index] = 0.0;
-       }
-       int c,d,e;
-       int ai,bi,ci,di,ei;
-       for (c = 0; c < num_symbols_per_reel; c++) {
-           for (d = 0; d < num_symbols_per_reel; d++) {
-	       for (e = 0; e < num_symbols_per_reel; e++) {
-	           symbol_weight_t lines[NUM_LINES][NUM_REELS];
-		   for(i = 0; i < NUM_LINES; i++) {
-		       int possible_line[NUM_REELS];
-		       int j = 0;
-		       for(j = 0; j < NUM_REELS; j++) {
-		           possible_line[j] = device_possible_lines[i*NUM_REELS + j];
-		       }
-		       ai = a_index + possible_line[0];
-		       if (ai == num_symbols_per_reel) {
-		           ai = 0;
-		       }
-		       if (ai < 0) {
-		       	   ai = num_symbols_per_reel-1;
-		       }
-		       bi = b_index + possible_line[1];
-		       if (bi == num_symbols_per_reel) {
-		           bi = 0;
-		       }
-		       if (bi < 0) {
-		           bi = num_symbols_per_reel-1;
-		       }
-		       ci = c + possible_line[2];
-		       if (ci == num_symbols_per_reel) {
-		           ci = 0;
-		       }
-		       if (ci < 0) {
-		           ci = num_symbols_per_reel-1;
-		       }
-		       di = d + possible_line[3];
-		       if (di == num_symbols_per_reel) {
-		           di = 0;
-		       }
-		       if (di < 0) {
-		           di = num_symbols_per_reel-1;
-		       }
-		       ei = e + possible_line[4];
-		       if (ei == num_symbols_per_reel) {
-		       	   ei = 0;
-		       }
-		       if (ei < 0) {
-		           ei = num_symbols_per_reel-1;
-		       }
-		       lines[i][0] = device_symbols_weights[ai*NUM_REELS];
-		       lines[i][1] = device_symbols_weights[bi*NUM_REELS + 1];
-		       lines[i][2] = device_symbols_weights[ci*NUM_REELS + 2];
-		       lines[i][3] = device_symbols_weights[di*NUM_REELS + 3];
-		       lines[i][4] = device_symbols_weights[ei*NUM_REELS + 4];
-		}
-		
-		for(i = 0; i < NUM_LINES; i++) {
-		      int j = 0;
-		      for(j = 0; j < num_payouts; j++) {
-		      	    if(isWin(device_payouts[j], lines[i])) {
-			    	device_payout_frequencies[device_index] += 1;
-				int k = 0;
-				double probability = 1.0;
-				for(k = 0; k < NUM_REELS; k++) {
-				    probability *= lines[0][k].weight;
-				}
-				probability /= total_choices;
-                                double expected_value = device_payouts[j].value * probability;
-                                for(k=i; k < NUM_LINES; k++) {
-				    int index = (device_index * NUM_LINES) + k;
-				    device_expected_values[index] += expected_value;
-				}
-			    }
-			}
-		    }					
-  	        }
-	    }
+    int c_index = blockIdx.y;
+    if (a_index < num_symbols_per_reel && b_index < num_symbols_per_reel && c_index < num_symbols_per_reel) {
+        const int device_index = a_index + num_symbols_per_reel * (b_index + num_symbols_per_reel * c_index);
+        device_payout_frequencies[device_index] = 0;
+        int i;
+        for(i = 0; i < NUM_LINES; i++) {
+            int index = (device_index * NUM_LINES) + i;
+	        device_expected_values[index] = 0.0;
+        }
+        int d,e;
+        int ai,bi,ci,di,ei;
+        for (d = 0; d < num_symbols_per_reel; d++) {
+            for (e = 0; e < num_symbols_per_reel; e++) {
+                symbol_weight_t lines[NUM_LINES][NUM_REELS];
+                for(i = 0; i < NUM_LINES; i++) {
+                    int possible_line[NUM_REELS];
+                    int j = 0;
+                    for(j = 0; j < NUM_REELS; j++) {
+                       possible_line[j] = device_possible_lines[i*NUM_REELS + j];
+                    }
+                    ai = a_index + possible_line[0];
+                    if (ai == num_symbols_per_reel) {
+                       ai = 0;
+                    }
+                    if (ai < 0) {
+                       ai = num_symbols_per_reel-1;
+                    }
+                    bi = b_index + possible_line[1];
+                    if (bi == num_symbols_per_reel) {
+                       bi = 0;
+                    }
+                    if (bi < 0) {
+                       bi = num_symbols_per_reel-1;
+                    }
+                    ci = c_index + possible_line[2];
+                    if (ci == num_symbols_per_reel) {
+                       ci = 0;
+                    }
+                    if (ci < 0) {
+                       ci = num_symbols_per_reel-1;
+                    }
+                    di = d + possible_line[3];
+                    if (di == num_symbols_per_reel) {
+                       di = 0;
+                    }
+                    if (di < 0) {
+                       di = num_symbols_per_reel-1;
+                    }
+                    ei = e + possible_line[4];
+                    if (ei == num_symbols_per_reel) {
+                       ei = 0;
+                    }
+                    if (ei < 0) {
+                       ei = num_symbols_per_reel-1;
+                    }
+                    lines[i][0] = device_symbols_weights[ai*NUM_REELS];
+                    lines[i][1] = device_symbols_weights[bi*NUM_REELS + 1];
+                    lines[i][2] = device_symbols_weights[ci*NUM_REELS + 2];
+                    lines[i][3] = device_symbols_weights[di*NUM_REELS + 3];
+                    lines[i][4] = device_symbols_weights[ei*NUM_REELS + 4];
+                }
+
+                for(i = 0; i < NUM_LINES; i++) {
+                    int j = 0;
+                    for(j = 0; j < num_payouts; j++) {
+                        if(isWin(device_payouts[j], lines[i])) {
+                            device_payout_frequencies[device_index] += 1;
+                            int k = 0;
+                            double probability = 1.0;
+                            for(k = 0; k < NUM_REELS; k++) {
+                                probability *= lines[0][k].weight;
+                            }
+                            probability /= total_choices;
+                            double expected_value = device_payouts[j].value * probability;
+                            for(k=i; k < NUM_LINES; k++) {
+                                int index = (device_index * NUM_LINES) + k;
+                                device_expected_values[index] += expected_value;
+                            }
+                        }
+                    }
+                }
+            }
         }
     }
 }

    }

    //copy device payout frequencies to host payout frequencies
    error = cudaMemcpy(payout_frequencies, device_payout_frequencies, num_symbols_per_reel_sq * sizeof(int), cudaMemcpyDeviceToHost);
    if (error != cudaSuccess){
        fprintf(stderr, "Failed to copy payout frequencies %d from device to host (error code %s)!\n", i, cudaGetErrorString(error));
        exit(EXIT_FAILURE);

    int j;
    for (i=0; i < NUM_LINES; i++) {
        double expected_value = 0.0;
        for(j = 0; j < num_symbols_per_reel_third; j++) {
	    int index = j * NUM_LINES + i;
            expected_value += expected_values[index];
        }
