void calcGoal(MatchTime mt, boolean shootout) {
		assert (home != null && away != null);
		Tactics.GamePlay homeGamePlay = home.getTactics().getGamePlay();
		Tactics.Effort homeEffort = home.getTactics().getEffort();
		Tactics.Defense homeDefense = home.getTactics().getDefense();
		Tactics.Offense homeOffense = home.getTactics().getOffense();
		Tactics.GamePlay awayGamePlay = away.getTactics().getGamePlay();
		Tactics.Effort awayEffort = away.getTactics().getEffort();
		Tactics.Defense awayDefense = away.getTactics().getDefense();
		Tactics.Offense awayOffense = away.getTactics().getOffense();

		// calc goals
		boolean homeWasShooting = false;
		int strength;
		int ranRange;
		int tune; // controller according tactics:
		// the greater tune, the less goals

		int nofHomePlayers = onIce.homePlayer.GetNofPlayers();
		int nofAwayPlayers = onIce.awayPlayer.GetNofPlayers();

		// calc strength of home team
		int homeStrength = 0;
		int collectPos = 0; // check for having correct positions
		for (int i = 0; i < nofHomePlayers; i++) {
			Player player = onIce.homePlayer.GetPlayer(i);
			Position.PosID posID = player.getPosition().getPosID();
			if (posID != Position.PosID.GOALIE) {
				// defense/offense tactics
				int playerStrength = player.getTotalStrengthWithMot();
				playerStrength *= 10; // 20 bytes code, ?? cycles
				if (homeDefense == Tactics.Defense.ZONE) {
					playerStrength += (player.getSkill() + player.getDefense()) / 2;
				} else {
					assert (homeDefense == Tactics.Defense.MARK);
					playerStrength += player.getPower();
				}
				if (homeOffense == Tactics.Offense.SHOOT) {
					playerStrength += player.getShooting();
				} else {
					assert (homeOffense == Tactics.Offense.PASS);
					playerStrength += (player.getPassing() + player
							.getOffense()) / 2;
				}
				playerStrength = playerStrength / 12;
				homeStrength += playerStrength;
				if (posID == Position.PosID.DEFENDER) {
					collectPos += 100;
				} else if (posID == Position.PosID.LEFTWING) {
					collectPos += 25;
				} else if (posID == Position.PosID.RIGHTWING) {
					collectPos -= 25;
				} else {
					assert (posID == Position.PosID.CENTER);
				}
			}
		}
		if (collectPos != 200) {
			// check for having correct positions
			homeStrength -= homeStrength / 10;
			if (collectPos < 150 || collectPos > 250) {
				homeStrength -= homeStrength / 10;
				if (collectPos < 100 || collectPos > 300) {
					homeStrength -= homeStrength / 10;
				}
			}
		}
		homeStrength /= 5;
		assert (homeStrength < 120 && homeStrength >= 0); // 6 field players,
		// div through 5
		if (home.getTeamState().getTeamStateID() == TeamState.TeamStateID.COACHED) {
			// game level
			if (Options.level == Options.Level.PROF && homeStrength > 0) {
				homeStrength--;
			} else if (Options.level == Options.Level.ROOKIE) {
				homeStrength++;
			}
		}

		// calc strength of away team
		int awayStrength = 0;
		collectPos = 0; // check for having correct positions
		for (int i = 0; i < nofAwayPlayers; i++) {
			Player player = onIce.awayPlayer.GetPlayer(i);
			Position.PosID posID = player.getPosition().getPosID();
			if (posID != Position.PosID.GOALIE) {
				// defense/offense tactics
				int playerStrength = player.getTotalStrengthWithMot();
				playerStrength *= 10;
				if (awayDefense == Tactics.Defense.ZONE) {
					playerStrength += (player.getSkill() + player.getDefense()) / 2;
				} else {
					assert (awayDefense == Tactics.Defense.MARK);
					playerStrength += player.getPower();
				}
				if (awayOffense == Tactics.Offense.SHOOT) {
					playerStrength += player.getShooting();
				} else {
					assert (awayOffense == Tactics.Offense.PASS);
					playerStrength += (player.getPassing() + player
							.getOffense()) / 2;
				}
				playerStrength = playerStrength / 12;
				awayStrength += playerStrength;
				if (posID == Position.PosID.DEFENDER) {
					collectPos += 100;
				} else if (posID == Position.PosID.LEFTWING) {
					collectPos += 25;
				} else if (posID == Position.PosID.RIGHTWING) {
					collectPos -= 25;
				} else {
					assert (posID == Position.PosID.CENTER);
				}
			}
		}
		if (collectPos != 200) {
			// check for having correct positions
			awayStrength -= awayStrength / 10;
			if (collectPos < 150 || collectPos > 250) {
				awayStrength -= awayStrength / 10;
				if (collectPos < 100 || collectPos > 300) {
					awayStrength -= awayStrength / 10;
				}
			}
		}
		awayStrength /= 5;
		assert (awayStrength < 120 && awayStrength >= 0); // 6 field players,
		// div through 5
		if (away.getTeamState().getTeamStateID() == TeamState.TeamStateID.COACHED) {
			// game level
			if (Options.level == Options.Level.PROF && awayStrength > 0) {
				awayStrength--;
			} else if (Options.level == Options.Level.ROOKIE) {
				awayStrength++;
			}
		}

		// calc shots/goals of away team
		// normalize strength
		float normalizeFactor = (float) 100 / (homeStrength + awayStrength);

		// Calc Shots/Goals: Consider opponents strength too.
		strength = (int) ((2 * homeStrength - awayStrength) * normalizeFactor);
		tune = 18; // normal tune
		if (homeGamePlay == Tactics.GamePlay.OFFENSIVE) {
			tune--;
		} else if (homeGamePlay == Tactics.GamePlay.DEFENSIVE) {
			tune++;
		} else {
			assert (homeGamePlay == Tactics.GamePlay.NORMAL_GP);
		}
		if (awayGamePlay == Tactics.GamePlay.OFFENSIVE) {
			tune--;
		} else if (awayGamePlay == Tactics.GamePlay.DEFENSIVE) {
			tune++;
		} else {
			assert (awayGamePlay == Tactics.GamePlay.NORMAL_GP);
		}
		if (homeEffort == Tactics.Effort.FULL) {
			tune--;
		} else if (homeEffort == Tactics.Effort.EASY) {
			tune++;
		} else {
			assert (homeEffort == Tactics.Effort.NORMAL_EFF);
		}
		if (awayEffort == Tactics.Effort.FULL) {
			tune++;
		} else if (awayEffort == Tactics.Effort.EASY) {
			tune--;
		} else {
			assert (awayEffort == Tactics.Effort.NORMAL_EFF);
		}
		ranRange = 3 * tune + 50 - strength;
		if (Util.random(ranRange > 0 ? ranRange : 1) == 0 && nofHomePlayers > 1) {
			homeWasShooting = true;
			setHomeShots(getHomeShots() + 1);
			this.report.setHomeShots(this.report.getHomeShots() + 1);
			Player goaliePlayer = onIce.awayPlayer.GetPlayer(0);
			if (goaliePlayer == null
					|| Util.random((goaliePlayer.getTotalStrength() + 50) / 20) == 0
					|| goaliePlayer.getPosition().getPosID() != Position.PosID.GOALIE
			// goalie replaced by field player
			) {
				// goalie could not save the shot
				currHomeScore++;
				getEvent().bitSet.set(GOAL_HOME);
				// goal
				if (shootout) {
					// shoot out after overtime
					// calculation should be improved ...
					// NYI
					this.report.setGoals(this.report.getGoals()
							+ home.getTeamName());
					this.report.setGoals(this.report.getGoals()
							+ Util.getModelResourceBundle().getString("L_WINS_SHOOTOUT"));
					this.report.setGoals(this.report.getGoals() + "\n");
				} else {
					Player goalPlayer = this.onIce.homePlayer.GetPlayer(Util
							.random(nofHomePlayers - 1) + 1);
					if (goalPlayer.getPosition().getPosID() == Position.PosID.DEFENDER
							|| goalPlayer.getPosition().getPosID() == Position.PosID.GOALIE
							|| goalPlayer.getTotalStrength() < strength) {
						// calc again to give forwards and strong players a
						// greater chance
						goalPlayer = this.onIce.homePlayer.GetPlayer(Util
								.random(nofHomePlayers - 1) + 1);
					}
					goalPlayer.updateMatchSecond(
							Player.MatchPlayerEvent.GOAL_SHOT, 0);
					// a goal against the goalie (but only for REAL goalies!)
					if (goaliePlayer != null
							&& goaliePlayer.getPosition().getPosID() == Position.PosID.GOALIE) {
						goaliePlayer.updateMatchSecond(
								Player.MatchPlayerEvent.GOAL_RECEIVED, 0);
					}
					this.report.setGoals(this.report.getGoals()
							+ Integer.toString(mt.getMin() + 1));
					this.report.setGoals(this.report.getGoals() + ". ");
					this.report.setGoals(this.report.getGoals()
							+ Integer.toString(currHomeScore));
					this.report.setGoals(this.report.getGoals() + ":");
					this.report.setGoals(this.report.getGoals()
							+ Integer.toString(currAwayScore));
					this.report.setGoals(this.report.getGoals() + " ");
					if (goalPlayer.isMultipleName()) {
						this.report.setGoals(this.report.getGoals()
								+ goalPlayer.getFirstName());
						this.report.setGoals(this.report.getGoals()
								+ " ");
					}
					this.report.setGoals(this.report.getGoals()
							+ goalPlayer.getLastName());
					// 1st assist
					Player assistPlayer = this.onIce.homePlayer.GetPlayer(Util
							.random(nofHomePlayers - 1) + 1);
					if (assistPlayer.getPosition().getPosID() == Position.PosID.DEFENDER
							|| assistPlayer.getPosition().getPosID() == Position.PosID.GOALIE) {
						// more points for forwards
						assistPlayer = this.onIce.homePlayer.GetPlayer(Util
								.random(nofHomePlayers - 1) + 1);
					}
					if (assistPlayer != goalPlayer) {
						assistPlayer.updateMatchSecond(
								Player.MatchPlayerEvent.ASSIST, 0);
						this.report.setGoals(this.report.getGoals()
								+ " (");
						if (assistPlayer.isMultipleName()) {
							this.report.setGoals(this.report.getGoals()
									+ assistPlayer.getFirstName());
							this.report.setGoals(this.report.getGoals()
									+ " ");
						}
						this.report.setGoals(this.report.getGoals()
								+ assistPlayer.getLastName());
						Player assistPlayer2 = this.onIce.homePlayer
								.GetPlayer(Util.random(nofHomePlayers - 1) + 1);
						if (assistPlayer2 != goalPlayer
								&& assistPlayer2 != assistPlayer) {
							// 2nd assist
							assistPlayer2.updateMatchSecond(
									Player.MatchPlayerEvent.ASSIST, 0);
							this.report.setGoals(this.report.getGoals()
									+ ", ");
							if (assistPlayer2.isMultipleName()) {
								this.report.setGoals(this.report
										.getGoals() + assistPlayer2
												.getFirstName());
								this.report.setGoals(this.report
										.getGoals() + " ");
							}
							this.report.setGoals(this.report.getGoals()
									+ assistPlayer2.getLastName());
						}
						this.report.setGoals(this.report.getGoals()
								+ ")");
					}
					if (nofHomePlayers > nofAwayPlayers) {
						this.report.setGoals(this.report.getGoals()
								+ " PP");
					} else if (nofHomePlayers < nofAwayPlayers) {
						this.report.setGoals(this.report.getGoals()
								+ " SH");
					}
					if (goaliePlayer.getPosition().getPosID() != Position.PosID.GOALIE) {
						this.report.setGoals(this.report.getGoals()
								+ " EN"); // empty net info
					} else if (onIce.homePlayer.GetPlayer(0).getPosition()
							.getPosID() != Position.PosID.GOALIE) {
						this.report.setGoals(this.report.getGoals()
								+ " WG"); // without goalie
					} else if (assistPlayer == goalPlayer
							&& Util.random(50) == 25) {
						this.report.setGoals(this.report.getGoals()
								+ " PEN"); // penalty shot
					}
					this.report.setGoals(this.report.getGoals() + "\n");
					for (int i = 0; i < nofHomePlayers; i++) {
						onIce.homePlayer.GetPlayer(i).updateMatchSecond(
								Player.MatchPlayerEvent.NOTHING, 1);
					}
					for (int i = 0; i < nofAwayPlayers; i++) {
						onIce.awayPlayer.GetPlayer(i).updateMatchSecond(
								Player.MatchPlayerEvent.NOTHING, -1);
					}
					// return first player from penalty box (if any)
					if (nofHomePlayers > nofAwayPlayers
							&& penBox.awayPlayer.GetNofPlayers() > 0) {
						Player player = penBox.awayPlayer.GetPlayer(0);
						player.setPenMin(0);
						// player goes from penbox onto ice
						getEvent().bitSet.set(RETURN_FROM_PEN);
						penBox.awayPlayer.RemovePlayer(player);
						onIce.awayPlayer.InsertPlayer(player);
					}
					putOnIce(mt); // new lines
				}
			} else {
				// a save for the goalie (but only for REAL goalies!)
				if (goaliePlayer.getPosition().getPosID() == Position.PosID.GOALIE) {
					goaliePlayer.updateMatchSecond(
							Player.MatchPlayerEvent.SAVE, 0);
				}
			}
		}

		// calc shots/goals of away team
		// normalize strength
		// Calc Shots/Goals: Consider opponents strength too.
		strength = (int) ((2 * awayStrength - homeStrength) * normalizeFactor);
		tune = (advHome ? 22 : 18); // normal tune
		if (awayGamePlay == Tactics.GamePlay.OFFENSIVE) {
			tune--;
		} else if (awayGamePlay == Tactics.GamePlay.DEFENSIVE) {
			tune++;
		} else {
			assert (awayGamePlay == Tactics.GamePlay.NORMAL_GP);
		}
		if (homeGamePlay == Tactics.GamePlay.OFFENSIVE) {
			tune--;
		} else if (homeGamePlay == Tactics.GamePlay.DEFENSIVE) {
			tune++;
		} else {
			assert (homeGamePlay == Tactics.GamePlay.NORMAL_GP);
		}
		if (awayEffort == Tactics.Effort.FULL) {
			tune--;
		} else if (awayEffort == Tactics.Effort.EASY) {
			tune++;
		} else {
			assert (awayEffort == Tactics.Effort.NORMAL_EFF);
		}
		if (homeEffort == Tactics.Effort.FULL) {
			tune++;
		} else if (homeEffort == Tactics.Effort.EASY) {
			tune--;
		} else {
			assert (homeEffort == Tactics.Effort.NORMAL_EFF);
		}
		ranRange = 3 * tune + 50 - strength;
		if (!homeWasShooting && Util.random(ranRange > 0 ? ranRange : 1) == 0
				&& nofAwayPlayers > 1) {
			setAwayShots(getAwayShots() + 1);
			this.report.setAwayShots(this.report.getAwayShots() + 1);
			Player goaliePlayer = onIce.homePlayer.GetPlayer(0);
			if (goaliePlayer == null
					|| Util.random((goaliePlayer.getTotalStrength() + 50) / 20) == 0
					|| goaliePlayer.getPosition().getPosID() != Position.PosID.GOALIE
			// goalie replaced by field player
			) {
				// goalie could not save the shot
				currAwayScore++;
				getEvent().bitSet.set(GOAL_AWAY);
				// goal
				if (shootout) {
					// shoot out after overtime
					// calculation should be improved ...
					// NYI
					this.report.setGoals(this.report.getGoals()
							+ away.getTeamName());
					this.report.setGoals(this.report.getGoals()
							+ Util.getModelResourceBundle().getString("L_WINS_SHOOTOUT"));
					this.report.setGoals(this.report.getGoals() + "\n");
				} else {
					Player goalPlayer = this.onIce.awayPlayer.GetPlayer(Util
							.random(nofAwayPlayers - 1) + 1);
					if (goalPlayer.getPosition().getPosID() == Position.PosID.DEFENDER
							|| goalPlayer.getPosition().getPosID() == Position.PosID.GOALIE
							|| goalPlayer.getTotalStrength() < strength) {
						// calc again to give forwards and strong players a
						// greater chance
						goalPlayer = this.onIce.awayPlayer.GetPlayer(Util
								.random(nofAwayPlayers - 1) + 1);
					}
					goalPlayer.updateMatchSecond(
							Player.MatchPlayerEvent.GOAL_SHOT, 0); // goal
					// scorer
					// a goal against the goalie (but only for REAL goalies!)
					if (goaliePlayer != null
							&& goaliePlayer.getPosition().getPosID() == Position.PosID.GOALIE) {
						goaliePlayer.updateMatchSecond(
								Player.MatchPlayerEvent.GOAL_RECEIVED, 0); // goalie
						// received
					}
					this.report.setGoals(this.report.getGoals()
							+ Integer.toString(mt.getMin() + 1));
					this.report.setGoals(this.report.getGoals() + ". ");
					this.report.setGoals(this.report.getGoals()
							+ Integer.toString(currHomeScore));
					this.report.setGoals(this.report.getGoals() + ":");
					this.report.setGoals(this.report.getGoals()
							+ Integer.toString(currAwayScore));
					this.report.setGoals(this.report.getGoals() + " ");
					if (goalPlayer.isMultipleName()) {
						this.report.setGoals(this.report.getGoals()
								+ goalPlayer.getFirstName());
						this.report.setGoals(this.report.getGoals()
								+ " ");
					}
					this.report.setGoals(this.report.getGoals()
							+ goalPlayer.getLastName());
					// assist
					Player assistPlayer = this.onIce.awayPlayer.GetPlayer(Util
							.random(nofAwayPlayers - 1) + 1);
					if (assistPlayer.getPosition().getPosID() == Position.PosID.DEFENDER
							|| assistPlayer.getPosition().getPosID() == Position.PosID.GOALIE) {
						// more points for forwards
						assistPlayer = this.onIce.awayPlayer.GetPlayer(Util
								.random(nofAwayPlayers - 1) + 1);
					}
					if (assistPlayer != goalPlayer) {
						assistPlayer.updateMatchSecond(
								Player.MatchPlayerEvent.ASSIST, 0);
						this.report.setGoals(this.report.getGoals()
								+ " (");
						if (assistPlayer.isMultipleName()) {
							this.report.setGoals(this.report.getGoals()
									+ assistPlayer.getFirstName());
							this.report.setGoals(this.report.getGoals()
									+ " ");
						}
						this.report.setGoals(this.report.getGoals()
								+ assistPlayer.getLastName());
						Player assistPlayer2 = this.onIce.awayPlayer
								.GetPlayer(Util.random(nofAwayPlayers - 1) + 1);
						if (assistPlayer2 != goalPlayer
								&& assistPlayer2 != assistPlayer) {
							// 2nd assist
							assistPlayer2.updateMatchSecond(
									Player.MatchPlayerEvent.ASSIST, 0);
							this.report.setGoals(this.report.getGoals()
									+ ", ");
							if (assistPlayer2.isMultipleName()) {
								this.report.setGoals(this.report
										.getGoals() + assistPlayer2
												.getFirstName());
								this.report.setGoals(this.report
										.getGoals() + " ");
							}
							this.report.setGoals(this.report.getGoals()
									+ assistPlayer2.getLastName());
						}
						this.report.setGoals(this.report.getGoals()
								+ ")");
					}
					if (nofHomePlayers < nofAwayPlayers) {
						this.report.setGoals(this.report.getGoals()
								+ " PP");
					} else if (nofHomePlayers > nofAwayPlayers) {
						this.report.setGoals(this.report.getGoals()
								+ " SH");
					}
					if (goaliePlayer.getPosition().getPosID() != Position.PosID.GOALIE) {
						this.report.setGoals(this.report.getGoals()
								+ " EN"); // empty net info
					} else if (onIce.awayPlayer.GetPlayer(0).getPosition()
							.getPosID() != Position.PosID.GOALIE) {
						this.report.setGoals(this.report.getGoals()
								+ " WG"); // without goalie
					} else if (assistPlayer == goalPlayer
							&& Util.random(50) == 25) {
						this.report.setGoals(this.report.getGoals()
								+ " PEN"); // penalty shot
					}
					this.report.setGoals(this.report.getGoals() + "\n");
					for (int i = 0; i < nofAwayPlayers; i++) {
						onIce.awayPlayer.GetPlayer(i).updateMatchSecond(
								Player.MatchPlayerEvent.NOTHING, 1);
					}
					for (int i = 0; i < nofHomePlayers; i++) {
						onIce.homePlayer.GetPlayer(i).updateMatchSecond(
								Player.MatchPlayerEvent.NOTHING, -1);
					}
					// return first player from penalty box (if any)
					if (nofHomePlayers < nofAwayPlayers
							&& penBox.homePlayer.GetNofPlayers() > 0) {
						Player player = penBox.homePlayer.GetPlayer(0);
						player.setPenMin(0);
						// player goes from penbox onto ice
						getEvent().bitSet.set(RETURN_FROM_PEN);
						penBox.homePlayer.RemovePlayer(player);
						onIce.homePlayer.InsertPlayer(player);
					}
					putOnIce(mt); // new lines
				}
			} else {
				// a save for the goalie (but only for REAL goalies!)
				if (goaliePlayer.getPosition().getPosID() == Position.PosID.GOALIE) {
					goaliePlayer.updateMatchSecond(
							Player.MatchPlayerEvent.SAVE, 0);
				}
			}
		}
	}