unit GameService;
{$MODE ObjFpc}
{$H+}
interface
uses
Classes, SysUtils,
(* project units *)
Model, ServiceInterfaces, Helpers;
type
TGameBase = class(TObject)
private
function IsItemExistant(ItemId: Integer): Boolean;
function IsItemNonExistant(ItemId: Integer): Boolean;
function IsAttributeLower(ItemId, Value: Integer): Boolean;
function IsAttributeHigher(ItemId, Value: Integer): Boolean;
function IsAttributeEqual(ItemId, Value: Integer): Boolean;
procedure IncAttribute(AttributeId: Integer; Value: String);
procedure DecAttribute(AttributeId: Integer; Value: String);
procedure ResetAttribute(AttributeId: Integer);
procedure EnableItem(ItemId: Integer);
procedure DisableItem(ItemId: Integer);
procedure SwitchItem(ItemId: Integer);
protected
Dao: IReadonlyDao;
protected
FAttributes: TAttributeList;
FAvailableExits: TPageExitList;
FCurrentPage: TPage;
FGameTitle: String;
FItems: TItemList;
protected
function AreExitConditionsSatisfied(PageExit: TPageExit): Boolean;
procedure ExecuteAction(Action: TAction);
procedure ExecuteActionsOfPage(PageId: Integer);
function IsConditionSatisfied(Condition: TPageExitCondition): Boolean;
procedure CheckExits(ExitList: TPageExitList);
function GetValue(const Key: String): String;
procedure InitAttributeValues;
procedure LoadExits(PageId: Integer);
procedure LoadGameData;
procedure LoadStartPage;
procedure LoadPage(PageId: Integer);
public
destructor Destroy; override;
end;
TGameDependencies = record
Dao: IReadonlyDao;
end;
TGame = class(TGameBase)
public
constructor Create(Dependencies: TGameDependencies);
public
procedure InitGame;
procedure UseExit(ExitId: Integer);
public
function AvailableExits: TPageExitList;
function CurrentPage: TPage;
function GameTitle: String;
end;
implementation
function TGameBase.IsItemExistant(ItemId: Integer): Boolean;
var
Item: TItem;
begin
Result := False;
Item := FItems.FindById(ItemId);
if Assigned(Item) then
Result := Item.IsPresent;
end;
function TGameBase.IsItemNonExistant(ItemId: Integer): Boolean;
var
Item: TItem;
begin
Result := False;
Item := FItems.FindById(ItemId);
if Assigned(Item) then
Result := not Item.IsPresent;
end;
function TGameBase.IsAttributeLower(ItemId, Value: Integer): Boolean;
var
Attribute: TAttribute;
begin
Result := False;
Attribute := FAttributes.FindById(ItemId);
if Assigned(Attribute) then
Result := Attribute.Value < Value;
end;
function TGameBase.IsAttributeHigher(ItemId, Value: Integer): Boolean;
var
Attribute: TAttribute;
begin
Result := False;
Attribute := FAttributes.FindById(ItemId);
if Assigned(Attribute) then
Result := Attribute.Value > Value;
end;
function TGameBase.IsAttributeEqual(ItemId, Value: Integer): Boolean;
var
Attribute: TAttribute;
begin
Result := False;
Attribute := FAttributes.FindById(ItemId);
if Assigned(Attribute) then
Result := Attribute.Value = Value;
end;
procedure TGameBase.IncAttribute(AttributeId: Integer; Value: String);
var
Attribute: TAttribute;
begin
Attribute := FAttributes.FindById(AttributeId);
if Assigned(Attribute) then
Attribute.Value := Attribute.Value + Helpers.CalculateValue(Attribute.Value, Value);
end;
procedure TGameBase.DecAttribute(AttributeId: Integer; Value: String);
var
Attribute: TAttribute;
begin
Attribute := FAttributes.FindById(AttributeId);
if Assigned(Attribute) then
Attribute.Value := Attribute.Value - Helpers.CalculateValue(Attribute.Value, Value);
end;
procedure TGameBase.ResetAttribute(AttributeId: Integer);
var
Attribute: TAttribute;
begin
Attribute := FAttributes.FindById(AttributeId);
if Assigned(Attribute) then
Attribute.Value := StrToInt(Attribute.InitialValue);
end;
procedure TGameBase.EnableItem(ItemId: Integer);
var
Item: TItem;
begin
Item := FItems.FindById(ItemId);
Item.IsPresent := True;
end;
procedure TGameBase.DisableItem(ItemId: Integer);
var
Item: TItem;
begin
Item := FItems.FindById(ItemId);
Item.IsPresent := False;
end;
procedure TGameBase.SwitchItem(ItemId: Integer);
var
Item: TItem;
begin
Item := FItems.FindById(ItemId);
Item.IsPresent := not Item.IsPresent;
end;
function TGameBase.AreExitConditionsSatisfied(PageExit: TPageExit): Boolean;
var
ConditionsList: TPageExitConditionList;
o: TPageExitCondition;
begin
Result := True;
if PageExit.IsConditional then begin
ConditionsList := Dao.GetPageExitConditionsByPageExitId(PageExit.Id);
for o in ConditionsList do begin
if not IsConditionSatisfied(o) then Result := False;
end;
end;
end;
procedure TGameBase.ExecuteAction(Action: TAction);
begin
case Action.ActionType of
ACTIONTYPE_INC_ATTRIBUTE:
IncAttribute(Action.ActionObjectId, Action.ActionValue);
ACTIONTYPE_DEC_ATTRIBUTE:
DecAttribute(Action.ActionObjectId, Action.ActionValue);
ACTIONTYPE_RESET_ATTRIBUTE:
ResetAttribute(Action.ActionObjectId);
ACTIONTYPE_ENABLE_ITEM:
EnableItem(Action.ActionObjectId);
ACTIONTYPE_DISABLE_ITEM:
DisableItem(Action.ActionObjectId);
ACTIONTYPE_SWITCH_ITEM:
SwitchItem(Action.ActionObjectId);
end;
end;
procedure TGameBase.ExecuteActionsOfPage(PageId: Integer);
var
Actions: TActionList;
o: TAction;
begin
try
Actions := Dao.GetActionsByPageId(PageId);
for o in Actions do begin
ExecuteAction(o);
end;
finally
FreeAndNil(Actions);
end;
end;
function TGameBase.IsConditionSatisfied(Condition: TPageExitCondition): Boolean;
begin
case Condition.ConditionType of
CONDITIONTYPE_ITEM_EXISTANT:
Result := IsItemExistant(Condition.ConditionObjectId);
CONDITIONTYPE_ITEM_NONEXISTANT:
Result := IsItemNonExistant(Condition.ConditionObjectId);
CONDITIONTYPE_ATTRIBUTE_HIGHER:
Result := IsAttributeHigher(Condition.ConditionObjectId, Condition.ConditionValue);
CONDITIONTYPE_ATTRIBUTE_LOWER:
Result := IsAttributeLower(Condition.ConditionObjectId, Condition.ConditionValue);
CONDITIONTYPE_ATTRIBUTE_EQUAL:
Result := IsAttributeEqual(Condition.ConditionObjectId, Condition.ConditionValue);
else
Result := False;
end;
end;
procedure TGameBase.CheckExits(ExitList: TPageExitList);
var
o: TPageExit;
DeletionList: TPageExitList;
begin
try
DeletionList := TPageExitList.Create(False);
for o in ExitList do
if not AreExitConditionsSatisfied(o) then DeletionList.Add(o);
for o in DeletionList do
ExitList.Remove(o);
finally
FreeAndNil(DeletionList);
end;
end;
function TGameBase.GetValue(const Key: String): String;
var
Setting: TSetting;
begin
Result := EmptyStr;
try
Setting := Dao.GetSetting(Key);
if Assigned(Setting) then Result := Setting.Value;
finally
FreeAndNil(Setting);
end;
end;
procedure TGameBase.InitAttributeValues;
var
o: TAttribute;
begin
for o in FAttributes do begin
o.Value := Helpers.CalculateValue(0, o.InitialValue);
o.InitialValue := IntToStr(o.Value);
end;
end;
procedure TGameBase.LoadExits(PageId: Integer);
var
NewExits: TPageExitList;
begin
NewExits := Dao.GetPageExistsByPageId(PageId);
FAvailableExits.Clear;
FAvailableExits.Assign(NewExits);
end;
procedure TGameBase.LoadGameData;
begin
FAttributes := Dao.GetAllAttributes;
InitAttributeValues;
FItems := Dao.GetAllItems;
FGameTitle := GetValue('GameTitle');
end;
procedure TGameBase.LoadStartPage;
var
StartPageId: Integer;
begin
StartPageId := StrToIntDef(GetValue('StartPage'), 1);;
LoadPage(StartPageId);
end;
procedure TGameBase.LoadPage(PageId: Integer);
var
NewPage: TPage;
begin
NewPage := Dao.GetPage(PageId);
if Assigned(NewPage) then begin
LoadExits(PageId);
ExecuteActionsOfPage(PageId);
end;
end;
destructor TGameBase.Destroy;
begin
FreeAndNil(FItems);
FreeAndNil(FAttributes);
FreeAndNil(FAvailableExits);
FreeAndNil(FCurrentPage);
inherited Destroy;
end;
constructor TGame.Create(Dependencies: TGameDependencies);
begin
inherited Create;
Dao := Dependencies.Dao;
end;
procedure TGame.InitGame;
begin
LoadGameData;
LoadStartPage;
end;
procedure TGame.UseExit(ExitId: Integer);
var
Exit: TPageExit;
begin
Exit := FAvailableExits.FindById(ExitId);
if Assigned(Exit) then begin
LoadPage(Exit.PageId);
end;
end;
function TGame.CurrentPage: TPage;
begin
Result := FCurrentPage;
end;
function TGame.GameTitle: String;
begin
Result := FGameTitle;
end;
function TGame.AvailableExits: TPageExitList;
begin
Result := FAvailableExits;
end;
end.