Code of BattleshipGames

by Josh Blake: L6 Age ~17

program BattleshipGames;
{
    Copyright (c) 2014 Josh Blake

    Licensed under the Apache License, Version 2.0 (the "License"); you may not
    use this file except in compliance with the License, as described at
    http://www.apache.org/licenses/ and http://www.pp4s.co.uk/licenses/
}
{$APPTYPE CONSOLE}

uses
  SysUtils,
  Players in 'Players.pas',
  Game in 'Game.pas',
  Settings in 'Settings.pas',
  Placers in 'Placers.pas',
  UI in 'UI.pas',
  Grid in 'Grid.pas';

const
  GridSize : integer = 10;

function UIFactory(aGame: TGame; PlayerName: String): ConsoleUI; overload;
begin
  Result := ConsoleUI.Create(aGame, PlayerName);
end;

function UIFactory(aGame1, aGame2: TGame; aName1, aName2: String): ConsoleUI; overload;
begin
  Result := ConsoleUI.Create(aGame1, aGame2, aName1, aName2);
end;

procedure VersusGame;
var
  UserGame, ComputerGame: TGame;
  Player: User;
  Computer: AIEasy;
  PlayerPlacer: UserPlacer;
  CompPlacer: RandomPlacer;
  I: Integer;
  UI: TBaseUI;
begin
  //initialise vars
  UserGame := TGame.Create(10, True);
  ComputerGame := TGame.Create(10, False);

  UI := UIFactory(UserGame, ComputerGame, 'You', 'Computer');

  Computer := AIEasy.Create(ComputerGame, UI);
  Player := User.Create(UserGame, UI);
  PlayerPlacer := UserPlacer.Create(ComputerGame, UI);
  CompPlacer := RandomPlacer.Create(UserGame, UI);

  //place ships
  for I := 1 to 5 do begin
    PlayerPlacer.PlaceShip(SHIP_START_HP[I]);
    CompPlacer.PlaceShip(SHIP_START_HP[I]);
  end;

  //main loop
  while True do begin
    if Player.TakeTurn <> -1 then begin //User wins
      UI.ShowMessage('You win');
      Break;
    end;

    //Computer's turn
    if Computer.TakeTurn <> -1 then begin  //Computer wins
      UI.ShowMessage('You lose');
      Break;
    end;
  end;
end;

procedure UserGame;
var
  Game: TGame;
  Player: User;
  GuessResult, I: Integer;
  Placer: RandomPlacer;
  UI: TBaseUI;
begin
  Game := TGame.Create(10, True); //init game 
  UI := UIFactory(Game, 'You');
  //place ships
  Placer := RandomPlacer.Create(Game, UI);
  for I := 1 to 5 do
    Placer.PlaceShip(SHIP_START_HP[I]);

  Player := User.Create(Game, UI);

  repeat
    GuessResult := Player.TakeTurn;
  until GuessResult <> -1;

  UI.ShowMessage('You''ve won in ' + IntToStr(GuessResult) + ' turns');
end;

procedure AIGame;
var
  Game: TGame;
  Player: AIEasy;
  GuessResult, Sum, I, J: Integer;
  Placer: UserPlacer;
  UI: TBaseUI;
begin
  Sum := 0;
  Game := TGame.Create(10, False);
  UI := UIFactory(Game, 'Computer');
  Player := AIEasy.Create(Game, UI);
  Placer := UserPlacer.Create(Game, UI);
  for I := 1 to 5 do
    Placer.PlaceShip(SHIP_START_HP[I]);
  UI.ShowMessage('Running game, please wait a few minutes - do not press enter', False);
  repeat
    GuessResult := Player.TakeTurn;
  until GuessResult <> -1;
  Log('Total guesses: '+ IntToStr(GuessResult));
  UI.ShowMessage('Computer took ' + IntToStr(GuessResult) + ' turns');
end;

procedure TwoPlayer;
var
  Player1, Player2: User;
  Placer1, Placer2: UserPlacer;
  Game1, Game2: TGame;
  I: Integer;
  UI: TBaseUI;
begin
  //initialise vars
  Game1 := TGame.Create(10, True);
  Game2 := TGame.Create(10, True);
  UI := UIFactory(Game1, Game2, 'Player1', 'Player2');
  Player1 := User.Create(Game1, UI);
  Player2 := User.Create(Game2, UI);
  Placer1 := UserPlacer.Create(Game2, UI);
  Placer2 := UserPlacer.Create(Game1, UI);

  //place ships
  UI.ShowMessage('Player 2 look away now');
  for I := 1 to 5 do begin
    Placer1.PlaceShip(SHIP_START_HP[I]);
  end;
  UI.ShowMessage('Player 1 look away now');
  for I := 1 to 5 do begin
    Placer2.PlaceShip(SHIP_START_HP[I]);
  end;

  while True do begin
    UI.DisplayGame;
    if Player1.TakeTurn <> -1 then begin
      UI.ShowMessage('Player 1 wins!');
      Exit;
    end;

    UI.DisplayGame;
    if Player2.TakeTurn <> -1 then begin
      UI.ShowMessage('Player 2 wins!');
      Exit;
    end;
  end;
end;

procedure Help;
var
  UI: TBaseUI;
const
  NL = #13 + #10;  //Newline character
begin
  //construct fake UI
  UI := UIFactory(TGame.Create(10, True), 'help');
  UI.ShowMessage(
'GAME MODES' + NL +
'Just Guess: Ships are randomly placed and you try and guess them quickly' + NL +
'Watch the AI play: Place ships that the AI tries to find' + NL +
'Play against the computer: Both you and the computer places ships and you try ' +
'and find each other (traditional battleships against the computer)' + NL +
'Two Player: Same but play against a friend'+ NL + NL + NL +
'THE AI' + NL +
'The AI is quite stupid, it guesses randomly until it hits a ship. It then ' +
'guesses in a straight line to try and destroy that ship.'
);
end;

var
  Mode: Integer;

begin
  Randomize;
  repeat
    Mode := ConsoleUI.DisplayMenu;
    case Mode of
      1: UserGame;
      2: AIGame;
      3: VersusGame;
      4: TwoPlayer;
      5: Help;
    end;
  until Mode = 6;
end.
Programming - a skill for life!

by Josh Blake: L6 Age ~17