* @param client
	 * @param cgd
	 * @return
	 */
	public cgData op_chargen(final String input, final Client client, final cgData cgd) {
		final Player player = getPlayer(client);

		debug("T: " + cgd.t + " Step: " + cgd.step + " Answer: " + cgd.answer);

		int t = cgd.t;           // question or answer?
		int step = cgd.step;     // the step of chargen we are on
		int answer = cgd.answer; // the player's answer to the current input request
		boolean edit = cgd.edit; // are we editing (i.e. coming back after first run through and changing things)

		debug("Start: T is now " + t);

		if (t == 0) {
			// send("Step: " + step, client);
			debug("Step: " + step);

			switch (step) {
			case 1:
				if (edit) send("Player Race: " + player.getRace(), client);

				send("Please choose a race:", client);

				int si = 0;
				int n = 0;

				final StringBuilder sb = new StringBuilder();

				for (final Race race : races) {
					if (si < 2) {
						sb.append("" + n + ")" + Utils.padRight(race.getName(), 8) + " ");

						si++;
					}
					else if (si < 3) {
						sb.append("" + n + ")" + Utils.padRight(race.getName(), 8));

						si++;
					}
					else {
						send(sb.toString(), client);
						sb.delete(0, sb.length());
						si = 0;

						sb.append("" + n + ")" + Utils.padRight(race.getName(), 8) + " ");
					}

					n++;
				}

				// send("1) " + Utils.padRight("" + Races.ELF, 6) + " 2) " +
				// Utils.padRight("" + Races.HUMAN, 6) + " 3) " +
				// Utils.padRight("" + Races.DWARF, 6), client);
				// send("4) " + Utils.padRight("" + Races.GNOME, 6) + " 5) " +
				// Utils.padRight("" + Races.ORC, 6) + " 6) " +
				// Utils.padRight("" + Races.HALF_ELF, 6), client);

				break;
			case 2:
				if (edit) send("Player Gender: " + player.getGender(), client);

				send("Please choose a gender:", client);
				send("1) Female 2) Male 3) Other 4) Neuter (no gender)", client);

				break;
			case 3:
				if (edit) send("Player Class: " + player.getPClass(), client);

				send("Please choose a class:", client);

				// TODO Fix Hardcoded class options?

				if (module != null && module.hasClasses()) {
					final PClass[] classes = module.getRuleset().getClasses();

					final StringBuilder sb1 = new StringBuilder();

					int choice = 1;
					int count = 0;

					int index = 1;

					// deliberately skipping first element of array (index = 0)
					// because it should be NONE which isn't a valid choice
					while (index < classes.length) {
						PClass pcl = classes[index];

						// 1,2,3, 4!
						if (count < 3) {
							if (count < 2) sb1.append(" " + choice + ") " + Utils.padRight("" + pcl.getName(), 12));
							else           sb1.append(choice + ") " + Utils.padRight("" + pcl.getName(), 12));

							choice++;
							count++;

							index++;
						}
						else {
							send(sb1.toString(), client);
							sb1.delete(0, sb1.length());

							count = 0;
						}
					}
				}
				else {
					send(" 1) " + Utils.padRight("" + Classes.BARBARIAN, 12) + " 2) " + Utils.padRight("" + Classes.BARD, 12) + " 3) " + Utils.padRight("" + Classes.CLERIC, 12), client);
					send(" 4) " + Utils.padRight("" + Classes.DRUID, 12) + " 5) " + Utils.padRight("" + Classes.FIGHTER, 12) + " 6) " + Utils.padRight("" + Classes.MONK, 12), client);
					send(" 7) " + Utils.padRight("" + Classes.PALADIN, 12) + " 8) " + Utils.padRight("" + Classes.RANGER, 12) + " 9) " + Utils.padRight("" + Classes.ROGUE, 12), client);
					send("10) " + Utils.padRight("" + Classes.SORCERER, 12) + "11) " + Utils.padRight("" + Classes.WIZARD, 12) + " 0) " + Utils.padRight("" + Classes.NONE, 12), client);
				}

				break;
			case 4:
				if (edit) send("Player Alignment: " + player.getAlignment(), client);

				send("Please select an alignment:", client);

				for (int i = 1; i < 9; i = i + 3) {
					send("" + i + ") " + Utils.padRight("" + Alignments.values()[i], ' ', 14) + " " + (i + 1) + ") " + Utils.padRight("" + Alignments.values()[i + 1], ' ', 14) + " " + (i + 2) + ") " + Utils.padRight("" + Alignments.values()[i + 2], ' ', 14), client);
				}

				break;
			case 5:
				send(Utils.padRight("Race: ", ' ', 8) + player.getRace(), client);
				send(Utils.padRight("Gender: ", ' ', 8) + player.getGender(), client);
				send(Utils.padRight("Class: ", ' ', 8) + player.getPClass(), client);
				send(Utils.padRight("Align: ", ' ', 8) + player.getAlignment(), client);
				send("", client);
				send("Options:", client);
				send(" 1) Reset 2) Edit 3) Done", client);

				break;
			case 6:
				send("Edit What:", client);
				send("1) Race 2) Gender 3) Class 4) Alignment 5) Abort", client);

				break;
			default:
				break;
			}

			client.write("> ");

			t = 1;

			debug("T is now " + t);
		}
		else if (t == 1) {
			try {
				// if there is input
				if (!input.equals("")) answer = Integer.parseInt(input);
				// return the data unchanged
				else                   return cgd;

				// send("Answer: " + answer, client);
				debug("Answer: " + answer);

				// send("Entering Step " + step, client);
				debug("Entering Step " + step);

				if (step == 1) {
					// player.setRace(Races.getRace(answer));
					player.setRace(races.get(answer));

					send("You have chosen to be an " + player.getRace(), client);
					send("Player Race set to: " + player.getRace(), client);

					/*
					 * Ability[] ab = new Ability[] { Abilities.STRENGTH,
					 * Abilities.DEXTERITY, Abilities.CONSTITUTION,
					 * Abilities.INTELLIGENCE, Abilities.WISDOM,
					 * Abilities.CHARISMA };
					 */

					Ability[] ab = rules.getAbilities();

					int index = 0;

					// apply permanent stat adjustments according to race
					for (int value : (Races.getRace(answer)).getStatAdjust()) {
						player.setAbility(ab[index], player.getAbility(ab[index]) + value);
						index++;
					}

					send("", client);

					step++;

					if (edit) {
						edit = false;
						step = 5;
					}
				}
				else if (step == 2) {
					switch (answer) {
					case 1:
						player.setGender("Female");
						break;
					case 2:
						player.setGender("Male");
						break;
					case 3:
						player.setGender("Other");
						break;
					case 4:
						player.setGender("None");
						break;
					default:
						player.setGender("None");
						break;
					}

					// You are female/You are male/You have chosen to be
					// genderles/You have no gender
					send("Player Gender set to: " + player.getGender(), client);

					send("", client);

					step++;

					if (edit) {
						edit = false;
						step = 5;
					}
				}
				else if (step == 3) {
					player.setPClass(Classes.getClass(answer));

					send("You have chosen to pursue being a " + player.getClass(), client);
					send("Player Class set to: " + player.getPClass(), client);
					send("", client);

					step++;

					if (edit) {
						edit = false;
						step = 5;
					}
				}
				else if (step == 4) {

					if (answer >= 1 && answer <= 9) {
						player.setAlignment(Alignments.values()[answer]);

						send("Player Alignment set to: " + player.getAlignment(), client);
						send("", client);

						step++;

						if (edit) {
							edit = false;
							step = 5;
						}	
					}
					else {
						send("Invalid Alignment Selection. Try Again.", client);
						send("", client);
					}
				}
				else if (step == 5) {
					if (answer == 1) { // Reset
						player.setRace(Races.NONE);
						player.setGender("None");
						player.setPClass(Classes.NONE);
						player.setAlignment(Alignments.NONE);

						reset_character(player); // reset character data to defaults

						client.write("Resetting...");
						client.writeln("Done");

						step = 1;
					}
					else if (answer == 2) { // Edit
						step = 6;
					}
					else if (answer == 3) { // Exit
						// not sure whether I should do the above steps on the spot or in this function below,
						// by passing it the appropriate classes. I suppose either is doable

						generate_character(player); // generate basic character data based on choices

						step = 0;
						answer = 0;

						player.setEditor(Editors.NONE);

						send("Game> Editor Reset", client);

						player.setStatus("OOC");

						send("Game> Status Reset", client);

						send("Exiting...", client);

						return new cgData(-1, -1, -1, false);
					}
				}
				else if (step == 6) {
					switch (answer) {
					case 1:
						edit = true;
						step = 1;
						break;
					case 2:
						edit = true;
						step = 2;
						break;
					case 3:
						edit = true;
						step = 3;
						break;
					case 4:
						edit = true;
						step = 4;
						break;
					case 5:
						client.write("Abort Edit\n");
						edit = false;
						step = 5;
					default:
						break;
					}
				}

				t = 0;
				debug("T is now " + t);
			}
			catch (final NumberFormatException npe) {
				debug("op_chargen(): invalid step number (number format exception)");
				System.out.println("--- Stack Trace ---");
				npe.printStackTrace();
			}
		}

		return new cgData(t, step, answer, edit);
	}