Initial commit.

This commit is contained in:
Tim Ambrogi 2022-03-04 15:30:18 -05:00
commit 0aad97fa48
49 changed files with 23959 additions and 0 deletions

20
.gitattributes vendored Normal file
View File

@ -0,0 +1,20 @@
*.psd filter=lfs diff=lfs merge=lfs -text
*.spine filter=lfs diff=lfs merge=lfs -text
*.png filter=lfs diff=lfs merge=lfs -text
*.jpg filter=lfs diff=lfs merge=lfs -text
*.dds filter=lfs diff=lfs merge=lfs -text
*.bank filter=lfs diff=lfs merge=lfs -text
*.wav filter=lfs diff=lfs merge=lfs -text
*.dll filter=lfs diff=lfs merge=lfs -text
*.lib filter=lfs diff=lfs merge=lfs -text
*.a filter=lfs diff=lfs merge=lfs -text
*.prx filter=lfs diff=lfs merge=lfs -text
*.exe filter=lfs diff=lfs merge=lfs -text
*.elf filter=lfs diff=lfs merge=lfs -text
*.ogv filter=lfs diff=lfs merge=lfs -text
*.mp4 filter=lfs diff=lfs merge=lfs -text
*.gif filter=lfs diff=lfs merge=lfs -text
*.xcf filter=lfs diff=lfs merge=lfs -text
*.font filter=lfs diff=lfs merge=lfs -text
*.gnf filter=lfs diff=lfs merge=lfs -text
*.vcxproj.filters merge=union

352
.gitignore vendored Normal file
View File

@ -0,0 +1,352 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
*.gqs
docs/

2703
Doxyfile Normal file

File diff suppressed because it is too large Load Diff

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021 Tim Ambrogi
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

220
README.md Normal file
View File

@ -0,0 +1,220 @@
# SquidTasks 0.2.0
[TOC]
About Squid::Tasks
=================
Squid::Tasks is a header-only C++ library that implements high-level coroutine-based tasks. It was originally designed for use in video game development, but has uses within various other problem domains.
Squid::Tasks was written by Tim Ambrogi Saxon and Elliott Mahler at Giant Squid Studios, and is freely available under the MIT license.
Overview of Squid::Tasks
========================
Squid::Tasks is a header-only library consisting of several top-level headers within the include directory.
- ```Task.h``` - Task-handles and standard awaiters [REQUIRED]
- ```TaskManager.```h - Manager that runs and resumes a collection of tasks
- ```TokenList.h``` - Data structure for tracking decentralized state across multiple tasks
- ```FunctionGuard.h``` - Scope guard that calls a function as it leaves scope
- ```TaskFSM.h``` - Finite state machine that implements states using task factories
Sample projects can be found under the @c /samples directory.
Integrating Squid::Tasks
========================
Including the Headers
-------------------
To integrate the Squid::Tasks library into your project, we recommend first copying the entire include directory into your project. You must then add the path of the include directory to the list of include directories in your project.
In __Visual Studio__, this is done by right-clicking your project and selecting Properties. Then navigate to Configuration Properties -> C/C++ -> General, and add the the path to the include directory to “Additional Include Directories”.
![Include Directory Settings in Visual Studio](images/setup01.png "Configuring Additional Include Directories in Visual Studio")
Enabling Coroutines for C++14/17 (skip this step if using C++20)
----------------------------------------------------------------
C++ coroutines were only formally added to the standard with C++20. In order to use them with earlier standards (C++14 or C++17), you must enable coroutines using a special compiler-specific compile flag.
In __Visual Studio__, this is done by right-clicking your project and selecting Properties. Then navigate to Configuration Properties -> C/C++ -> Command Line, and add ```/await:strict``` to “Additional Options”:
![Enabling Coroutines in Visual Studio](images/setup02.png "Enabling Coroutines in Visual Studio")
If you are using __Clang__, you will need to add -fcoroutines-ts to your compiler command-line compilation parameters.
If you are using the __Clang Platform Toolset__ from within Visual Studio, you will need to add -Xclang -fcoroutines-ts to your compiler command-line compilation parameters.
Configure Squid::Tasks with TasksConfig.h
-----------------------------------------
The Squid::Tasks library can be configured in a variety of important ways. This is done by enabling and disabling preprocessor values within the include/TasksConfig.h file:
- **SQUID_ENABLE_TASK_DEBUG**: Enables Task debug callstack tracking and debug names via Task::GetDebugStack() and Task::GetDebugName()
- **SQUID_ENABLE_DOUBLE_PRECISION_TIME**: Switches time representation from 32-bit single-precision floats to 64-bit double-precision floats
- **SQUID_ENABLE_NAMESPACE**: Enables a Squid:: namespace around all classes in the Squid::Tasks library
- **SQUID_USE_EXCEPTIONS**: Enables experimental (largely-untested) exception-handling, and replaces all asserts with runtime_error exceptions
- **SQUID_ENABLE_GLOBAL_TIME**: Enables global time support (alleviating the need to specify a time stream for time-sensitive awaiters) **[see Appendix A for more details]**
An Example First Task
=====================
To get started using Squid::Tasks, the first step is to write and execute your first task from within your project. Many modern C++ game engines feature some sort of "actor" class - a game entity that exists within the scene and is updated each frame. Our example code assume this class exists, but the same principles will apply for projects that are written under a different paradigm.
The first step is to identify an actor class that would benefit from coroutine support, such as an enemy actor. Here is an example Enemy class from a hypothetical 2D game:
```cpp
class Enemy : public Actor
{
public:
void SetRotation(float in_degrees); // Set the rotation of the enemy
float GetRotation() const; // Get the rotation of the enemy
void SetPosition(Vec2f in_pos); // Set the position of the enemy
Vec2f GetPosition() const; // Get the position of th enemy
void MoveToward(Vec2f in_pos, float in_speed, float in_dt) const; // Move toward a target position at a given speed
void FireProjectileAt(Vec2f in_pos); // Fire a simple projectile to a target position
std::shared_ptr<Player> GetPlayer() const; // Get the location of the player actor
float GameTime() const; // Get the current game time (in seconds)
float DeltaTime() const; // Get the current frame's delta-time (in seconds)
virtual void OnInitialize() override // Automatically called when this enemy enters the scene
{
Actor::OnInitialize(); // Call the base Actor function
}
virtual void Tick(float in_dt) override // Automatically called every frame
{
Actor::Tick(in_dt); // Call the base Actor function
}
virtual void OnDestroy() override // Automatically called when this enemy leaves the scene
{
Actor::OnDestroy(); // Call the base Actor function
}
};
```
We want to try writing a simple enemy AI using Squid::Tasks. Conventionally, the ```Tick()``` function would be responsible for performing all AI logic calculations, so we will use that as the entry-point into our first task coroutine. First, we will create a ```TaskManager``` as a private member m_taskMgr. Then, we call ```m_taskMgr.Update()``` from within ```Tick()```. Lastly, we need to make sure all of tasks stop running as soon as the enemy leaves the scene, so we call ```m_taskMgr.KillAllTasks()``` from within ```OnDestroy()```.
```cpp
class Enemy : public Actor
{
public:
// ...
virtual void Tick(float in_dt) override // Automatically called every frame
{
Actor::Tick(in_dt); // Call the base Actor function
m_taskMgr.Update(); // Resume all active tasks once per tick
}
virtual void OnDestroy() override // Automatically called when this enemy leaves the scene
{
m_taskMgr.KillAllTasks(); // Kill all active tasks when we leave the scene
Actor::OnDestroy(); // Call the base Actor function
}
protected:
TaskManage m_taskMgr;
};
```
Now that we have the task manager hooked up, we can write and run our first task. Let's make our first task very simple, and just have it print out a string and then terminate. To create a task, we simply write a member function with returns type ```Task<>```, and make sure to use at least one co_await or co_return keyword within the function body. This tells the compiler to compile the function as a coroutine with Task<> as the handle type for the coroutine.
```cpp
class Enemy : public Actor
{
public:
// ...
virtual void OnInitialize() override // Automatically called when this enemy enters the scene
{
Actor::OnInitialize(); // Call the base Actor function
m_taskMgr.RunManaged(ManageEnemyAI()); // Run our task as a fire-and-forget "managed task"
}
// ...
Task<> ManageEnemyAI()
{
TASK_NAME(__FUNCTION__); // Gives the task a name for debugging purposes
printf("Hello, enemy AI!\n");
co_return; // Return from this task
}
};
```
With these changes, any enemy instance that enters the scene will print "Hello, enemy AI!". Note that we actually run the task from within ```OnInitialize()```. This line is what actually instantiates the task and tells the task manager to update it every frame. Now that we have the complete scaffolding in, we can try to write an actual enemy behavior. Let's try writing a simple chase AI that chases the player if they get too close to the enemy.
```cpp
class Enemy : public Actor
{
public:
// ...
Task<> ManageEnemyAI()
{
TASK_NAME(__FUNCTION__); // Gives the task a name for debugging purposes
while(true) // This "infinite loop" means this task should run for the enemy's lifetime
{
// Wait until player gets within a 100-pixel radius
co_await WaitUntil([&] {
return Distance(GetPlayer()->GetPosition(), GetPosition()) < 100.0f;
});
// Move toward the player as long as they are within a 100-pixel radius
while(Distance(GetPlayer()->GetPosition(), GetPosition()) < 100.0f)
{
MoveToward(GetPlayer()->GetPosition(), 100.0f, DeltaTime());
co_await Suspend();
}
// Cool-down for 2 seconds before following again
co_await WaitSeconds(2.0f, GameTime());
}
}
};
```
Our chase enemy AI is complete! One advantage of coroutines is that they tend to be fairly straightforward to read, so hopefully you can guess at what some of the above logic means. Regardless, let's break down how this works. The first thing we do is create a while(true) loop around our logic. This is a common coroutine pattern, but it can be confusing the first time you see it. In a normal function, an infinite loop would result in the thread soft-locking. However, in coroutines this pattern essentially means "this coroutine will run for the lifetime of the object running it", which is the desired behavior for our enemy AI task.
The next thing we see is the new ```co_await``` keyword. The ```co_await <awaiter>``` expression, when evaluated, will suspend the current task until the awaiter is ready to be resumed again. In this example we use 3 of the most versatile and powerful awaiters in Squid::Tasks:
- Suspend() -> Waits until the next time the task is resumed (usually a single frame)
- WaitSeconds() -> Waits until N seconds have passed in a given time-stream
- WaitUntil() -> Waits until a given function returns true
With these 3 awaiters, it is possible to implement enormously complex state machines with relatively straightforward code. (To learn about the other awaiters that come with Squid::Tasks, refer to the \ref Awaiters documentation.)
Next Steps
==========
Hopefully, this brief tutorial has given you an outline of the steps required to integrate coroutines into your own projects. From here, we recommend exploring the "GeneriQuest" sample project under ```samples/Sample_TextGame```. It demonstrates both simple and complex applications of coroutines in a simple text-based game example.
This is the end of the tutorial documentation (for now)! If you made it this far, please contact us at tim@giantsquidstudios.com to let us know any ways in which our documentation could have been more useful for you in learning to use Squid::Tasks!
Thank you for being one of our "early readers!" We appreciate your help in making this library a success. :)
Appendices
==========
APPENDIX A: Enabling Global Time Support
----------------------------------------
Every game project has its own method of updating and measuring game time. Most games feature multiple different "time-streams", such as "game time", "real time", "editor time", "paused time", "audio time", etc... Because of this, the Squid::Tasks library requires each time-sensitive awaiter (e.g. ```WaitSeconds()```, ```Timeout()```, etc) to be presented with a time-stream function that returns the current time in the desired time-stream. By convention, these time-streams are passed as functions into the final argument of time-sensitive awaiters.
A final (optional) step of integrating Squid::Tasks is to enable global time support and implement a global Squid::GetTime() function.
For less-complex projects it can be desirable to default to a "global time-stream" that removes the requirement to explicitly pass a time-stream function into time-sensitive awaiters. To enable this functionality, the user must set ```SQUID_ENABLE_GLOBAL_TIME``` in TasksConfig.h and implement a special function called Squid::GetTime(). Failure to define this function will result in a linker error.
The Squid::GetTime() function should return a floating-point value representing the number of seconds since the program started running. Here is an example Squid::GetTime() function implementation from within the ```main.cpp``` file of a sample project:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~.cpp
NAMESPACE_SQUID_BEGIN
tTaskTime GetTime()
{
return (tTaskTime)TimeSystem::GetTime();
}
NAMESPACE_SQUID_END
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
It is recommended to save off the current time value at the start of each game frame, returning that saved value from within ```Squid::GetTime()```. The reason for this is that, within a single frame, you likely want all of the tasks to behave as if they are updating at the same time. By providing the same exact time value to all Tasks that are resumed within a given update, the software is more likely to behave in a stable and predictable manner.

3
images/setup01.png Normal file
View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:32d4bd5fbf3b3fde29e4ef61a333c95d6bd3ecc4a6e397eaa948f53e11713b1c
size 14467

3
images/setup02.png Normal file
View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:b6eb86da0d21d6dd2688ca22d2456cb49a24fde6bf109d891b9d826a1f3f0d49
size 17307

128
include/FunctionGuard.h Normal file
View File

@ -0,0 +1,128 @@
#pragma once
/// @defgroup FunctionGuard Function Guard
/// @brief Scope guard that calls a function as it leaves scope.
/// @{
///
/// A FunctionGuard is an scope guard object that stores a functor that will be called from its destructor. By
/// convention, scope guards are move-only objects that are intended for allocation on the stack, to ensure that certain
/// operations are performed exactly once (when their scope collapses).
///
/// Because tasks can be canceled while suspended (and thus do not reach the end of the function), any cleanup code at
/// the end of a task isn't guaranteed to execute. Because FunctionGuard is an RAII object, it gives programmers an
/// opportunity to schedule guaranteed cleanup code, no matter how a task terminates.
///
/// Consider the following example of a task that manages a character's "charge attack" in a combat-oriented game:
///
/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
///
/// class Character : public Actor
/// {
/// public:
/// Task<> ChargeAttackState()
/// {
/// bool bIsFullyCharged = false;
/// if(Input->IsAttackButtonPressed())
/// {
/// StartCharging(); // Start playing charge effects
/// auto stopChargingGuard = MakeFnGuard([&]{
/// StopCharging(); // Stop playing charge effects
/// });
///
/// // Wait for N seconds (canceling if button is no longer held)
/// bIsFullyCharged = co_await WaitSeconds(chargeTime).CancelIf([&] {
/// return !Input->IsAttackButtonPressed();
/// });
/// } // <-- This is when StopCharging() will be called
/// FireShot(bIsFullyCharged);
/// }
/// };
///
/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
///
/// In the above example, we can guarantee that StopCharging will logically be called exactly once for every call to
/// StartCharging(), even the ChargeAttackState() task is killed or canceled. Furthermore, we know that StopCharging()
/// will always be called prior to the call to FireShot().
///
/// In practice, it is often desirable to create more domain-specific scope guards for specific use cases, but
/// FunctionGuard provides a simple general-purpose tool for writing robust, water-tight coroutine logic without the
/// overhead of creating bespoke support classes.
//--- User configuration header ---//
#include "TasksConfig.h"
NAMESPACE_SQUID_BEGIN
template <typename tFn = TFunction<void()>>
class FunctionGuard
{
public:
FunctionGuard() = default; /// Default constructor
FunctionGuard(nullptr_t) /// Null-pointer constructor
{
}
FunctionGuard(tFn in_fn) /// Functor constructor
: m_fn(MoveTemp(in_fn))
{
}
~FunctionGuard() /// Destructor
{
Execute();
}
FunctionGuard(FunctionGuard&& in_other) noexcept /// Move constructor
: m_fn(MoveTemp(in_other.m_fn))
{
in_other.Forget();
}
FunctionGuard& operator=(FunctionGuard<tFn>&& in_other) noexcept /// Move assignment operator
{
m_fn = MoveTemp(in_other.m_fn);
in_other.Forget();
return *this;
}
FunctionGuard& operator=(nullptr_t) noexcept /// Null-pointer assignment operator (calls Forget() to clear the functor)
{
Forget();
return *this;
}
operator bool() const /// Convenience conversion operator that calls IsBound()
{
return IsBound();
}
bool IsBound() noexcept /// Returns whether functor has been bound to this FunctionGuard
{
return m_fn;
}
void Execute() /// Executes and clears the functor (if bound)
{
if(m_fn)
{
m_fn.GetValue()();
Forget();
}
}
void Forget() noexcept /// Clear the functor (without calling it)
{
m_fn.Reset();
}
private:
TOptional<tFn> m_fn; // The function to call when this scope guard is destroyed
};
/// Create a function guard (directly stores the concretely-typed functor in the FunctionGuard)
template <typename tFn>
FunctionGuard<tFn> MakeFnGuard(tFn in_fn)
{
return FunctionGuard<tFn>(MoveTemp(in_fn));
}
/// Create a generic function guard (preferable when re-assigning new functor values to the same variable)
inline FunctionGuard<> MakeGenericFnGuard(TFunction<void()> in_fn)
{
return FunctionGuard<>(MoveTemp(in_fn));
}
NAMESPACE_SQUID_END
///@} end of FunctionGuard group

View File

@ -0,0 +1,220 @@
// WARNING: This is an internal implementation header, which must be included from a specific location/namespace
// That is the reason that this header does not contain a #pragma once, nor namespace guards
// Helper struct representing a transition event to a new FSM state
struct TransitionEvent
{
Task<> newTask;
StateId newStateId;
};
// Base class for defining links between states
class LinkBase
{
public:
virtual ~LinkBase() = default;
virtual TOptional<TransitionEvent> EvaluateLink(const tOnStateTransitionFn& in_onTransitionFn) const = 0;
};
// Type-safe link handle
class LinkHandle
{
bool IsOnCompleteLink() const
{
return m_linkType == eType::OnComplete;
}
bool HasCondition() const
{
return m_isConditionalLink;
}
protected:
// Link-type enum
enum class eType
{
Normal,
OnComplete,
};
// Friends
template<class, class> friend class StateHandle;
friend class ::TaskFSM;
// Constructors (friend-only)
LinkHandle() = delete;
LinkHandle(TSharedPtr<LinkBase> in_link, eType in_linkType, bool in_isConditional)
: m_link(MoveTemp(in_link))
, m_linkType(in_linkType)
, m_isConditionalLink(in_isConditional)
{
}
TOptional<TransitionEvent> EvaluateLink(const tOnStateTransitionFn& in_onTransitionFn) const
{
return m_link->EvaluateLink(in_onTransitionFn);
}
private:
TSharedPtr<LinkBase> m_link; // The underlying link
eType m_linkType; // Whether the link is normal or OnComplete
bool m_isConditionalLink; // Whether the link has an associated condition predicate
};
// Internal FSM state object
template<class tStateInput, class tStateConstructorFn>
struct State
{
State(tStateConstructorFn in_stateCtorFn, StateId in_stateId, FString in_debugName)
: stateCtorFn(in_stateCtorFn)
, stateId(in_stateId)
, debugName(in_debugName)
{
}
tStateConstructorFn stateCtorFn;
StateId stateId;
FString debugName;
};
// Internal FSM state object (exit state specialization)
template<>
struct State<void, void>
{
State(StateId in_stateId, FString in_debugName)
: stateId(in_stateId)
, debugName(in_debugName)
{
}
StateId stateId;
FString debugName;
};
// Internal link definition object
template<class ReturnT, class tStateConstructorFn, class tPredicateFn>
class Link : public LinkBase
{
public:
Link(TSharedPtr<State<ReturnT, tStateConstructorFn>> in_targetState, tPredicateFn in_predicate)
: m_targetState(MoveTemp(in_targetState))
, m_predicate(in_predicate)
{
}
private:
virtual TOptional<TransitionEvent> EvaluateLink(const tOnStateTransitionFn& in_onTransitionFn) const final
{
TOptional<TransitionEvent> result;
if(TOptional<ReturnT> payload = m_predicate())
{
if(in_onTransitionFn)
{
in_onTransitionFn();
}
result = TransitionEvent{ m_targetState->stateCtorFn(payload.GetValue()), m_targetState->stateId };
}
return result;
}
TSharedPtr<State<ReturnT, tStateConstructorFn>> m_targetState;
tPredicateFn m_predicate;
};
// Internal link definition object (no-payload specialization)
template<class tStateConstructorFn, class tPredicateFn>
class Link<void, tStateConstructorFn, tPredicateFn> : public LinkBase
{
public:
Link(TSharedPtr<State<void, tStateConstructorFn>> in_targetState, tPredicateFn in_predicate)
: m_targetState(MoveTemp(in_targetState))
, m_predicate(in_predicate)
{
}
private:
virtual TOptional<TransitionEvent> EvaluateLink(const tOnStateTransitionFn& in_onTransitionFn) const final
{
TOptional<TransitionEvent> result;
if(m_predicate())
{
if(in_onTransitionFn)
{
in_onTransitionFn();
}
result = TransitionEvent{ m_targetState->stateCtorFn(), m_targetState->stateId };
}
return result;
}
TSharedPtr<State<void, tStateConstructorFn>> m_targetState;
tPredicateFn m_predicate;
};
// Internal link definition object (exit-state specialization)
template<class tPredicateFn>
class Link<void, void, tPredicateFn> : public LinkBase
{
public:
Link(TSharedPtr<State<void, void>> in_targetState, tPredicateFn in_predicate)
: m_targetState(MoveTemp(in_targetState))
, m_predicate(in_predicate)
{
}
private:
virtual TOptional<TransitionEvent> EvaluateLink(const tOnStateTransitionFn& in_onTransitionFn) const final
{
TOptional<TransitionEvent> result;
if(m_predicate())
{
if(in_onTransitionFn)
{
in_onTransitionFn();
}
result = TransitionEvent{ Task<>(), m_targetState->stateId };
}
return result;
}
TSharedPtr<State<void, void>> m_targetState;
tPredicateFn m_predicate;
};
// Specialized type traits that deduce the first argument type of an arbitrary callable type
template <typename tRet, typename tArg>
static tArg get_first_arg_type(TFunction<tRet(tArg)> f); // Return type is first argument type
template <typename tRet>
static void get_first_arg_type(TFunction<tRet()> f); // Return type is void (function has no arguments)
template <typename T>
struct function_traits : public function_traits<decltype(&T::operator())> // Generic callable objects (use operator())
{
};
template <typename tRet, typename... tArgs> // Function
struct function_traits<tRet(tArgs...)>
{
using tFunction = TFunction<tRet(tArgs...)>;
using tArg = decltype(get_first_arg_type(tFunction()));
};
template <typename tRet, typename... tArgs> // Function ptr
struct function_traits<tRet(*)(tArgs...)>
{
using tFunction = TFunction<tRet(tArgs...)>;
using tArg = decltype(get_first_arg_type(tFunction()));
};
template <typename tClass, typename tRet, typename... tArgs> // Member function ptr (const)
struct function_traits<tRet(tClass::*)(tArgs...) const>
{
using tFunction = TFunction<tRet(tArgs...)>;
using tArg = decltype(get_first_arg_type(tFunction()));
};
template <typename tClass, typename tRet, typename... tArgs> // Member function ptr
struct function_traits<tRet(tClass::*)(tArgs...)>
{
using tFunction = TFunction<tRet(tArgs...)>;
using tArg = decltype(get_first_arg_type(tFunction()));
};

View File

@ -0,0 +1,896 @@
// WARNING: This is an internal implementation header, which must be included from a specific location/namespace
// That is the reason that this header does not contain a #pragma once, nor namespace guards
enum class eTaskRef;
template <typename tRet> class TaskPromise;
class TaskInternalBase;
template <typename tRet> class TaskInternal;
//--- tTaskReadyFn ---//
using tTaskReadyFn = TFunction<bool()>;
template <typename tRet, eTaskRef RefType, eTaskResumable Resumable>
auto CancelTaskIf(Task<tRet, RefType, Resumable>&& in_task, tTaskCancelFn in_cancelFn);
template <typename tRet, eTaskRef RefType, eTaskResumable Resumable>
auto StopTaskIf(Task<tRet, RefType, Resumable>&& in_task, tTaskCancelFn in_cancelFn);
template <typename tRet, eTaskRef RefType, eTaskResumable Resumable, typename tTimeFn>
auto StopTaskIf(Task<tRet, RefType, Resumable>&& in_task, tTaskCancelFn in_cancelFn, tTaskTime in_timeout, tTimeFn in_timeFn);
template <typename tRet, eTaskRef RefType, eTaskResumable Resumable, typename T>
auto StopTaskIf(Task<tRet, RefType, Resumable>&& in_task, tTaskCancelFn in_cancelFn, tTaskTime in_timeout);
//--- Suspend-If Awaiter ---//
struct SuspendIf
{
SuspendIf(bool in_suspend)
: m_suspend(in_suspend)
{
}
bool await_ready() noexcept { return !m_suspend; }
void await_suspend(std::coroutine_handle<>) noexcept {}
void await_resume() noexcept {}
private:
bool m_suspend;
};
//--- Task Debug Stack Formatter ---//
struct TaskDebugStackFormatter
{
// Format function (formats a debug output string) [virtual]
virtual FString Format(const FString& in_str) const
{
FString result = Indent(0);
int32_t indent = 0;
int32_t start = 0;
int32_t found = 0;
while((found = in_str.FindChar('\n', start)) != INDEX_NONE)
{
int32_t end = found + 1;
if((found < in_str.Len() - 1) && (in_str[found + 1] == '`')) // indent
{
++indent;
++end;
}
else if((found >= 1) && (in_str[found - 1] == '`')) // dedent
{
--indent;
--found;
}
result += in_str.Mid(start, found - start) + '\n' + Indent(indent);
start = end;
}
result += in_str.Mid(start);
return result;
}
virtual FString Indent(int32_t in_indent) const
{
return FString::ChrN(in_indent * 2, ' ');
}
};
static FString FormatDebugString(FString in_str)
{
in_str.ReplaceCharInline('\n', ' ');
in_str.LeftChopInline(32, false);
return in_str;
}
//--- SetDebugName Awaiter ---//
#if SQUID_ENABLE_TASK_DEBUG
struct SetDebugName
{
// Sets a Task's debug name field
SetDebugName(const char* in_name)
: m_name(in_name)
{
}
SetDebugName(const char* in_name, TFunction<FString()> in_dataFn)
: m_name(in_name)
, m_dataFn(in_dataFn)
{
}
private:
template <typename tRet> friend class TaskPromiseBase;
const char* m_name = nullptr;
TFunction<FString()> m_dataFn;
};
#endif //SQUID_ENABLE_TASK_DEBUG
//--- AddStopTask Awaiter ---//
template <typename tRet, eTaskRef RefType, eTaskResumable Resumable>
struct AddStopTaskAwaiter
{
AddStopTaskAwaiter(Task<tRet, RefType, Resumable>& in_taskToStop)
: m_taskToStop(&in_taskToStop)
{
}
private:
template <typename tRet> friend class TaskPromiseBase;
Task<tRet, RefType, Resumable>* m_taskToStop = nullptr;
};
template <typename tRet, eTaskRef RefType, eTaskResumable Resumable>
auto AddStopTask(Task<tRet, RefType, Resumable>& in_taskToStop)
{
return AddStopTaskAwaiter<tRet, RefType, Resumable>(in_taskToStop);
};
//--- RemoveStopTask Awaiter ---//
template <typename tRet, eTaskRef RefType, eTaskResumable Resumable>
struct RemoveStopTaskAwaiter
{
RemoveStopTaskAwaiter(Task<tRet, RefType, Resumable>& in_taskToStop)
: m_taskToStop(&in_taskToStop)
{
}
private:
template <typename tRet> friend class TaskPromiseBase;
Task<tRet, RefType, Resumable>* m_taskToStop = nullptr;
};
template <typename tRet, eTaskRef RefType, eTaskResumable Resumable>
auto RemoveStopTask(Task<tRet, RefType, Resumable>& in_taskToStop)
{
return RemoveStopTaskAwaiter<tRet, RefType, Resumable>(in_taskToStop);
};
//--- Task Awaiter ---//
template <typename tRet, eTaskRef RefType, eTaskResumable Resumable, typename promise_type>
struct TaskAwaiterBase
{
TaskAwaiterBase(const Task<tRet, RefType, Resumable>& in_task)
{
// This constructor exists to minimize downstream compile-error spam when co_awaiting a non-copyable Task by copy
}
TaskAwaiterBase(Task<tRet, RefType, Resumable>&& in_task)
: m_task(MoveTemp(in_task))
{
SQUID_RUNTIME_CHECK(m_task.IsValid(), "Tried to await an invalid task");
}
TaskAwaiterBase(TaskAwaiterBase&& in_taskAwaiter) noexcept
{
m_task = MoveTemp(in_taskAwaiter.m_task);
}
bool await_ready() noexcept
{
if(m_task.IsDone())
{
return true;
}
return false;
}
template <eTaskResumable UResumable = Resumable, typename std::enable_if_t<UResumable == eTaskResumable::Yes>* = nullptr>
bool await_suspend(std::coroutine_handle<promise_type> in_coroHandle) noexcept
{
// Set the sub-task on the suspending task
auto& promise = in_coroHandle.promise();
auto taskInternal = promise.GetInternalTask();
auto subTaskInternal = m_task.GetInternalTask();
if(taskInternal->IsStopRequested())
{
subTaskInternal->RequestStop(); // Propagate any stop request to new sub-tasks
}
taskInternal->SetSubTask(StaticCastSharedPtr<TaskInternalBase>(subTaskInternal));
// Resume the task
if(m_task.Resume() == eTaskStatus::Done)
{
taskInternal->SetSubTask(nullptr);
return false; // Do not suspend, because the task is done
}
return true; // Suspend, because the task is not done
}
template <eTaskResumable UResumable = Resumable, typename std::enable_if_t<UResumable == eTaskResumable::No>* = nullptr>
bool await_suspend(std::coroutine_handle<promise_type> in_coroHandle) noexcept
{
auto& promise = in_coroHandle.promise();
if(!m_task.IsDone())
{
promise.SetReadyFunction([this] { return m_task.IsDone(); });
return true; // Suspend, because the task is not done
}
return false; // Do not suspend, because the task is done
}
protected:
auto GetInternalTask() const
{
return m_task.GetInternalTask();
}
Task<tRet, RefType, Resumable> m_task;
};
template <typename tRet, eTaskRef RefType, eTaskResumable Resumable, typename promise_type>
struct TaskAwaiter : public TaskAwaiterBase<tRet, RefType, Resumable, promise_type>
{
using TaskAwaiterBase<tRet, RefType, Resumable, promise_type>::TaskAwaiterBase;
template <typename U = tRet, typename std::enable_if_t<!std::is_void<U>::value>* = nullptr>
auto await_resume()
{
this->m_task.RethrowUnhandledException(); // Re-throw any exceptions
auto retVal = this->m_task.TakeReturnValue();
SQUID_RUNTIME_CHECK(retVal, "Awaited task return value is unset");
return MoveTemp(retVal.GetValue());
}
template <typename U = tRet, typename std::enable_if_t<std::is_void<U>::value>* = nullptr>
void await_resume()
{
this->m_task.RethrowUnhandledException(); // Re-throw any exceptions
}
};
//--- Future Awaiter ---//
template <typename tRet, typename promise_type>
struct FutureAwaiter
{
FutureAwaiter(TFuture<tRet>&& in_future)
: m_future(MoveTemp(in_future))
{
}
~FutureAwaiter()
{
}
FutureAwaiter(FutureAwaiter&& in_futureAwaiter) noexcept
{
m_future = MoveTemp(in_futureAwaiter.m_future);
}
bool await_ready() noexcept
{
bool isReady = m_future.IsReady();
return isReady;
}
bool await_suspend(std::coroutine_handle<promise_type> in_coroHandle) noexcept
{
// Set the ready function
auto& promise = in_coroHandle.promise();
// Suspend if future is not ready
bool shouldSuspend = !m_future.IsReady();
if(shouldSuspend)
{
promise.SetReadyFunction([this] { return m_future.IsReady(); });
}
return shouldSuspend;
}
template <typename U = tRet, typename std::enable_if_t<!std::is_void<U>::value>* = nullptr>
auto await_resume()
{
return m_future.Get();
}
template <typename U = tRet, typename std::enable_if_t<std::is_void<U>::value>* = nullptr>
void await_resume()
{
m_future.Get();
}
private:
TFuture<tRet> m_future;
};
//--- Shared Future Awaiter ---//
template <typename tRet, typename promise_type>
struct SharedFutureAwaiter
{
SharedFutureAwaiter(const TSharedFuture<tRet>& in_sharedFuture)
: m_sharedFuture(in_sharedFuture)
{
}
bool await_ready() noexcept
{
bool isReady = m_sharedFuture.IsReady();
return isReady;
}
bool await_suspend(std::coroutine_handle<promise_type> in_coroHandle) noexcept
{
// Set the ready function
auto& promise = in_coroHandle.promise();
// Suspend if future is not ready
bool shouldSuspend = !m_sharedFuture.IsReady();
if(shouldSuspend)
{
promise.SetReadyFunction([this] { return m_sharedFuture.IsReady(); });
}
return shouldSuspend;
}
template <typename U = tRet, typename std::enable_if_t<!std::is_void<U>::value>* = nullptr>
auto await_resume()
{
return m_sharedFuture.Get();
}
template <typename U = tRet, typename std::enable_if_t<std::is_void<U>::value>* = nullptr>
void await_resume()
{
m_sharedFuture.Get(); // Trigger any pending errors
}
private:
TSharedFuture<tRet> m_sharedFuture;
};
//--- TaskPromiseBase ---//
template <typename tRet>
class alignas(16) TaskPromiseBase
{
public:
// Type aliases
using promise_type = TaskPromise<tRet>;
using tTaskInternal = TaskInternal<tRet>;
// Destructor
~TaskPromiseBase()
{
// NOTE: Destructor is non-virtual, because it is always handled + destroyed as its concrete type
m_taskInternal->OnTaskPromiseDestroyed();
}
// Coroutine interface functions
auto initial_suspend() noexcept
{
return std::suspend_always();
}
auto final_suspend() noexcept
{
return std::suspend_always();
}
auto get_return_object()
{
return std::coroutine_handle<promise_type>::from_promise(*static_cast<promise_type*>(this));
}
static TSharedPtr<tTaskInternal> get_return_object_on_allocation_failure()
{
SQUID_THROW(std::bad_alloc(), "Failed to allocate memory for Task");
return {};
}
//----------------------------------------------------------------------------
// HACK: Coroutines in UE5 under MSVC is currently causing a memory underrun
// These allocators are a workaround for the issue (as is alignas(16))
void* operator new(size_t Size) noexcept
{
const size_t WorkaroundAlign = std::alignment_of<TaskPromiseBase>();
Size += WorkaroundAlign;
return (void*)((uint8_t*)FMemory::Malloc(Size, WorkaroundAlign) + WorkaroundAlign);
}
void operator delete(void* Ptr) noexcept
{
const size_t WorkaroundAlign = std::alignment_of<TaskPromiseBase>();
auto OffsetPtr = (uint8_t*)Ptr - WorkaroundAlign;
FMemory::Free(OffsetPtr);
}
//----------------------------------------------------------------------------
#if SQUID_NEEDS_UNHANDLED_EXCEPTION
void unhandled_exception() noexcept
{
#if SQUID_USE_EXCEPTIONS
// Propagate exceptions for handling
m_taskInternal->SetUnhandledException(std::current_exception());
#endif //SQUID_USE_EXCEPTIONS
}
#endif // SQUID_NEEDS_UNHANDLED_EXCEPTION
// Internal Task
void SetInternalTask(tTaskInternal* in_taskInternal)
{
m_taskInternal = in_taskInternal;
}
tTaskInternal* GetInternalTask()
{
return m_taskInternal;
}
const tTaskInternal* GetInternalTask() const
{
return m_taskInternal;
}
// Ready Function
void SetReadyFunction(const tTaskReadyFn& in_taskReadyFn)
{
m_taskInternal->SetReadyFunction(in_taskReadyFn);
}
// Await-Transforms
auto await_transform(Suspend in_awaiter)
{
return in_awaiter;
}
auto await_transform(std::suspend_never in_awaiter)
{
return in_awaiter;
}
#if SQUID_ENABLE_TASK_DEBUG
auto await_transform(SetDebugName in_awaiter)
{
m_taskInternal->SetDebugName(in_awaiter.m_name);
m_taskInternal->SetDebugDataFn(in_awaiter.m_dataFn);
return std::suspend_never();
}
#endif //SQUID_ENABLE_TASK_DEBUG
template <typename tRet, eTaskRef RefType, eTaskResumable Resumable>
auto await_transform(AddStopTaskAwaiter<tRet, RefType, Resumable> in_awaiter)
{
m_taskInternal->AddStopTask(*in_awaiter.m_taskToStop);
return std::suspend_never();
}
template <typename tRet, eTaskRef RefType, eTaskResumable Resumable>
auto await_transform(RemoveStopTaskAwaiter<tRet, RefType, Resumable> in_awaiter)
{
m_taskInternal->RemoveStopTask(*in_awaiter.m_taskToStop);
return std::suspend_never();
}
auto await_transform(GetStopContext in_awaiter)
{
struct GetStopContextAwaiter : public std::suspend_never
{
GetStopContextAwaiter(StopContext in_stopCtx)
: stopCtx(in_stopCtx)
{
}
auto await_resume() noexcept
{
return stopCtx;
}
StopContext stopCtx;
};
GetStopContextAwaiter stopCtxAwaiter{ m_taskInternal->GetStopContext() };
return stopCtxAwaiter;
}
auto await_transform(const tTaskReadyFn& in_taskReadyFn)
{
// Check if we are already ready, and suspend if we are not
bool isReady = in_taskReadyFn();
if(!isReady)
{
m_taskInternal->SetReadyFunction(in_taskReadyFn);
}
return SuspendIf(!isReady); // Suspend if the function isn't already ready
}
template <typename tFutureRet>
auto await_transform(TFuture<tFutureRet>&& in_future)
{
return FutureAwaiter<tFutureRet, promise_type>(MoveTemp(in_future));
}
template <typename tFutureRet>
auto await_transform(const TSharedFuture<tFutureRet>& in_sharedFuture)
{
return SharedFutureAwaiter<tFutureRet, promise_type>(in_sharedFuture);
}
// Task Await-Transforms
template <typename tTaskRet, eTaskRef RefType, eTaskResumable Resumable,
typename std::enable_if_t<Resumable == eTaskResumable::Yes>* = nullptr>
auto await_transform(Task<tTaskRet, RefType, Resumable>&& in_task) // Move version
{
return TaskAwaiter<tTaskRet, RefType, Resumable, promise_type>(MoveTemp(in_task));
}
template <typename tTaskRet, eTaskRef RefType, eTaskResumable Resumable,
typename std::enable_if_t<Resumable == eTaskResumable::No>* = nullptr>
auto await_transform(Task<tTaskRet, RefType, Resumable> in_task) // Copy version (Non-Resumable)
{
return TaskAwaiter<tTaskRet, RefType, Resumable, promise_type>(MoveTemp(in_task));
}
template <typename tTaskRet, eTaskRef RefType, eTaskResumable Resumable,
typename std::enable_if_t<Resumable == eTaskResumable::Yes>* = nullptr>
auto await_transform(const Task<tTaskRet, RefType, Resumable>& in_task) // Invalid copy version (Resumable)
{
static_assert(static_false<tTaskRet>::value, "Cannot await a non-copyable (resumable) Task by copy (try co_await MoveTemp(task), co_await WeakTaskHandle(task), or co_await task.WaitUntilDone()");
return TaskAwaiter<tTaskRet, RefType, Resumable, promise_type>(MoveTemp(in_task));
}
protected:
tTaskInternal* m_taskInternal = nullptr;
};
//--- TaskPromise ---//
template <typename tRet>
class TaskPromise : public TaskPromiseBase<tRet>
{
public:
// Return value access
void return_value(const tRet& in_retVal) // Copy return value
{
this->m_taskInternal->SetReturnValue(in_retVal);
}
void return_value(tRet&& in_retVal) // Move return value
{
this->m_taskInternal->SetReturnValue(MoveTemp(in_retVal));
}
};
template <>
class TaskPromise<void> : public TaskPromiseBase<void>
{
public:
void return_void()
{
}
};
//--- TaskInternalBase ---//
class TaskInternalBase
{
public:
TaskInternalBase(std::coroutine_handle<> in_coroHandle)
: m_coroHandle(in_coroHandle)
{
SQUID_RUNTIME_CHECK(m_coroHandle, "Invalid coroutine handle passed into Task");
}
~TaskInternalBase() // NOTE: Destructor is intentionally non-virtual (shared_ptr preserves concrete type via deleter)
{
Kill(); // Used for killing subtasks
}
StopContext GetStopContext() const
{
return { &m_isStopRequested };
}
bool IsStopRequested() const
{
return m_isStopRequested;
}
void RequestStop() // Propagates a request for the task to come to a 'graceful' stop
{
m_isStopRequested = true;
for(auto& stopTask : m_stopTasks)
{
if(auto locked = stopTask.Pin())
{
locked->RequestStop();
}
}
m_stopTasks.SetNum(0);
}
template <typename tRet, eTaskRef RefType, eTaskResumable Resumable>
void AddStopTask(Task<tRet, RefType, Resumable>& in_taskToStop) // Adds a task to the list of tasks to which we propagate stop requests
{
if(m_isStopRequested)
{
in_taskToStop.RequestStop();
}
else if(in_taskToStop.IsValid())
{
m_stopTasks.Add(in_taskToStop.GetInternalTask());
}
}
template <typename tRet, eTaskRef RefType, eTaskResumable Resumable>
void RemoveStopTask(Task<tRet, RefType, Resumable>& in_taskToStop) // Removes a task to the list of tasks to which we propagate stop requests
{
if(in_taskToStop.IsValid())
{
for(int32_t i = 0; i < m_stopTasks.Num(); ++i)
{
if(m_stopTasks[i].Pin() == in_taskToStop.GetInternalTask())
{
m_stopTasks[i] = m_stopTasks.Last();
m_stopTasks.Pop();
return;
}
}
}
}
eTaskStatus Resume() // Returns whether the task is still running
{
// Make sure this task is not already mid-resume
SQUID_RUNTIME_CHECK(m_internalState != eInternalState::Resuming, "Attempted to resume Task while already resumed");
// Task is destroyed, therefore task is done
if(m_internalState == eInternalState::Destroyed)
{
return eTaskStatus::Done;
}
// Mark task as resuming
m_internalState = eInternalState::Resuming;
// Resume any active sub-task
if(m_subTaskInternal)
{
// Propagate any stop requests to sub-task prior to resuming
if(m_isStopRequested)
{
m_subTaskInternal->m_isStopRequested = true;
}
// Resume the sub-task
if(m_subTaskInternal->Resume() != eTaskStatus::Done)
{
m_internalState = eInternalState::Idle;
return eTaskStatus::Suspended; // Sub-task not done, therefore task is not done
}
// Clear the sub-task
m_subTaskInternal = nullptr;
}
// Resume task, if necessary
if(CanResume())
{
m_taskReadyFn = nullptr; // Clear any ready function we were waiting on
m_coroHandle.resume(); // Resume the underlying std::coroutine_handle
}
// Return to idle state and return current task status
auto taskStatus = m_coroHandle.done() ? eTaskStatus::Done : eTaskStatus::Suspended;
if(taskStatus == eTaskStatus::Done)
{
m_isDone = true; // Mark task done
}
m_internalState = eInternalState::Idle;
return taskStatus;
}
// Sub-task
void SetSubTask(TSharedPtr<TaskInternalBase> in_subTaskInternal)
{
m_subTaskInternal = in_subTaskInternal;
}
#if SQUID_ENABLE_TASK_DEBUG
// Debug task name + stack
FString GetDebugName() const
{
return (!IsDone() && m_debugDataFn) ? (FString(m_debugName) + " [" + m_debugDataFn() + "]") : m_debugName;
}
FString GetDebugStack() const
{
FString result = m_subTaskInternal ? (GetDebugName() + " -> " + m_subTaskInternal->GetDebugStack()) : GetDebugName();
return result;
}
void SetDebugName(const char* in_debugName)
{
if(in_debugName)
{
m_debugName = in_debugName;
}
}
void SetDebugDataFn(TFunction<FString()> in_debugDataFn)
{
m_debugDataFn = in_debugDataFn;
}
#endif //SQUID_ENABLE_TASK_DEBUG
// Exceptions
#if SQUID_USE_EXCEPTIONS
std::exception_ptr GetUnhandledException() const
{
if(m_isExceptionSet)
{
return m_exception;
}
return nullptr;
}
#endif //SQUID_USE_EXCEPTIONS
protected:
#if SQUID_USE_EXCEPTIONS
// Internal implementation of exception-setting (called by TaskInternal<> child classes)
void InternalSetUnhandledException(std::exception_ptr in_exception)
{
// NOTE: This must never be called more than once in the lifetime of an internal task
SQUID_RUNTIME_CHECK(!m_isExceptionSet, "Exception was set for a task after it had already been set");
if(!m_isExceptionSet)
{
m_exception = in_exception;
m_isExceptionSet = true;
}
}
#endif //SQUID_USE_EXCEPTIONS
private:
template <typename tRet> friend class TaskPromiseBase;
template <typename tRet, eTaskRef RefType, eTaskResumable Resumable, typename promise_type> friend struct TaskAwaiterBase;
template <typename tRet, eTaskRef RefType, eTaskResumable Resumable> friend class Task;
// Kill this task
void Kill() // Kill() can safely be called multiple times
{
SQUID_RUNTIME_CHECK(m_internalState != eInternalState::Resuming, "Attempted to kill Task while resumed");
if(m_internalState == eInternalState::Idle)
{
// Mark task done
m_isDone = true;
// First destroy any sub-tasks
if(m_subTaskInternal)
{
m_subTaskInternal->Kill();
}
// Destroy the underlying std::coroutine_handle
m_coroHandle.destroy(); // This should only ever be called directly from this one place
m_coroHandle = nullptr;
m_taskReadyFn = nullptr; // Clear out the ready function
m_internalState = eInternalState::Destroyed;
}
}
// Done + can-resume status
void SetReadyFunction(const tTaskReadyFn& in_taskReadyFn)
{
m_taskReadyFn = in_taskReadyFn;
}
bool CanResume() const
{
if(IsDone())
{
return false;
}
if(m_subTaskInternal)
{
bool canResume = m_subTaskInternal->CanResume();
return canResume;
}
bool isReady = !m_taskReadyFn || m_taskReadyFn();
return isReady;
}
bool IsDone() const
{
return m_isDone;
}
bool m_isDone = false;
// Internal state
enum class eInternalState
{
Idle,
Resuming,
Destroyed,
};
eInternalState m_internalState = eInternalState::Idle;
// Task ready condition (when awaiting a TFunction<bool>)
tTaskReadyFn m_taskReadyFn;
#if SQUID_USE_EXCEPTIONS
// Exceptions
std::exception_ptr m_exception = nullptr;
bool m_isExceptionSet = false;
#endif //SQUID_USE_EXCEPTIONS
// Sub-task
TSharedPtr<TaskInternalBase> m_subTaskInternal;
// Reference-counting (determines underlying std::coroutine_handle lifetime, not lifetime of this internal task)
void AddLogicalRef()
{
++m_refCount;
}
void RemoveLogicalRef()
{
--m_refCount;
if(m_refCount == 0)
{
Kill();
}
}
int32_t m_refCount = 0; // Number of (strong) non-weak tasks referencing the internal task
// C++ std::coroutine_handle
std::coroutine_handle<> m_coroHandle;
// Stop request
bool m_isStopRequested = false;
TArray<TWeakPtr<TaskInternalBase>> m_stopTasks;
#if SQUID_ENABLE_TASK_DEBUG
// Debug Data
const char* m_debugName = "[unnamed task]";
TFunction<FString()> m_debugDataFn;
#endif //SQUID_ENABLE_TASK_DEBUG
};
//--- TaskInternal ---//
template <typename tRet>
class TaskInternal : public TaskInternalBase
{
public:
using promise_type = TaskPromise<tRet>;
TaskInternal(std::coroutine_handle<promise_type> in_handle)
: TaskInternalBase(in_handle)
{
auto& promisePtr = in_handle.promise();
promisePtr.SetInternalTask(this);
}
#if SQUID_USE_EXCEPTIONS
void SetUnhandledException(std::exception_ptr in_exception)
{
m_retValState = eTaskRetValState::Orphaned; // Return value can never be set if there was an unhandled exception
InternalSetUnhandledException(in_exception);
}
#endif //SQUID_USE_EXCEPTIONS
void SetReturnValue(const tRet& in_retVal)
{
tRet retVal = in_retVal;
SetReturnValue(MoveTemp(retVal));
}
void SetReturnValue(tRet&& in_retVal)
{
if(m_retValState == eTaskRetValState::Unset)
{
m_retVal = MoveTemp(in_retVal);
m_retValState = eTaskRetValState::Set;
return;
}
// These conditions should (logically) never be met, but they are included in case future changes violate that constraint
SQUID_RUNTIME_CHECK(m_retValState != eTaskRetValState::Set, "Attempted to set a task's return value when it was already set");
SQUID_RUNTIME_CHECK(m_retValState != eTaskRetValState::Taken, "Attempted to set a task's return value after it was already taken");
SQUID_RUNTIME_CHECK(m_retValState != eTaskRetValState::Orphaned, "Attempted to set a task's return value after it was orphaned");
}
TOptional<tRet> TakeReturnValue()
{
// If the value has been set, mark it as taken and move-return the value
if(m_retValState == eTaskRetValState::Set)
{
m_retValState = eTaskRetValState::Taken;
return MoveTemp(m_retVal);
}
// If the value was not set, return an unset optional (checking that it was neither taken nor orphaned)
SQUID_RUNTIME_CHECK(m_retValState != eTaskRetValState::Taken, "Attempted to take a task's return value after it was already successfully taken");
SQUID_RUNTIME_CHECK(m_retValState != eTaskRetValState::Orphaned, "Attempted to take a task's return value that will never be set (task ended prematurely)");
return {};
}
void OnTaskPromiseDestroyed()
{
// Mark the return value as orphaned if it was never set
m_retValState = eTaskRetValState::Orphaned;
}
private:
// Internal state
enum class eTaskRetValState
{
Unset, // Has not yet been set
Set, // Has been set and can be taken
Taken, // Has been taken and can no longer be taken
Orphaned, // Will never be set because the TaskPromise has been destroyed
};
eTaskRetValState m_retValState = eTaskRetValState::Unset; // Initially unset
TOptional<tRet> m_retVal;
};
template <>
class TaskInternal<void> : public TaskInternalBase
{
public:
using promise_type = TaskPromise<void>;
TaskInternal(std::coroutine_handle<promise_type> in_handle)
: TaskInternalBase(in_handle)
{
auto& promisePtr = in_handle.promise();
promisePtr.SetInternalTask(this);
}
#if SQUID_USE_EXCEPTIONS
void SetUnhandledException(std::exception_ptr in_exception)
{
InternalSetUnhandledException(in_exception);
}
#endif //SQUID_USE_EXCEPTIONS
void TakeReturnValue() // This function is an intentional no-op, to simplify certain templated function implementations
{
}
void OnTaskPromiseDestroyed()
{
}
};

View File

@ -0,0 +1,236 @@
#pragma once
//--- User configuration header ---//
#include "../TasksConfig.h"
// Namespace macros (enabled/disabled via SQUID_ENABLE_NAMESPACE)
#if SQUID_ENABLE_NAMESPACE
#define NAMESPACE_SQUID_BEGIN namespace Squid {
#define NAMESPACE_SQUID_END }
#define NAMESPACE_SQUID Squid
#else
#define NAMESPACE_SQUID_BEGIN
#define NAMESPACE_SQUID_END
#define NAMESPACE_SQUID
namespace Squid {} // Convenience to allow 'using namespace Squid' even when namespace is disabled
#endif
// Exception macros (to support environments with exceptions disabled)
#if SQUID_USE_EXCEPTIONS && (defined(__cpp_exceptions) || defined(__EXCEPTIONS))
#include <stdexcept>
#define SQUID_THROW(exception, errStr) throw exception;
#define SQUID_RUNTIME_ERROR(errStr) throw std::runtime_error(errStr);
#define SQUID_RUNTIME_CHECK(condition, errStr) if(!(condition)) throw std::runtime_error(errStr);
#else
#include <cassert>
#define SQUID_THROW(exception, errStr) assert(false && errStr);
#define SQUID_RUNTIME_ERROR(errStr) assert(false && errStr);
#define SQUID_RUNTIME_CHECK(condition, errStr) assert((condition) && errStr);
#endif //__cpp_exceptions
// Time Interface
NAMESPACE_SQUID_BEGIN
#if SQUID_ENABLE_DOUBLE_PRECISION_TIME
using tTaskTime = double;
#else
using tTaskTime = float; // Defines time units for use with the Task system
#endif //SQUID_ENABLE_DOUBLE_PRECISION_TIME
NAMESPACE_SQUID_END
// Coroutine de-optimization macros [DEPRECATED]
#ifdef _MSC_VER
#if _MSC_VER >= 1920
// Newer versions of Visual Studio (>= VS2019) compile coroutines correctly
#define COROUTINE_OPTIMIZE_OFF
#define COROUTINE_OPTIMIZE_ON
#else
// Older versions of Visual Studio had code generation bugs when optimizing coroutines (they would compile, but have incorrect runtime results)
#define COROUTINE_OPTIMIZE_OFF __pragma(optimize("", off))
#define COROUTINE_OPTIMIZE_ON __pragma(optimize("", on))
#endif // _MSC_VER >= 1920
#else
// The Clang compiler has sometimes crashed when optimizing/inlining certain coroutines, so this macro can be used to disable inlining
#define COROUTINE_OPTIMIZE_OFF _Pragma("clang optimize off")
#define COROUTINE_OPTIMIZE_ON _Pragma("clang optimize on")
#endif
// False type for use in static_assert() [static_assert(false, ...) -> static_assert(static_false<T>, ...)]
template<typename T>
struct static_false : std::false_type
{
};
// Determine C++ Language Version
#if defined(_MSVC_LANG)
#define CPP_LANGUAGE_VERSION _MSVC_LANG
#elif defined(__cplusplus)
#define CPP_LANGUAGE_VERSION __cplusplus
#else
#define CPP_LANGUAGE_VERSION 0L
#endif
#if CPP_LANGUAGE_VERSION > 201703L // C++20 or higher
#define HAS_CXX17 1
#define HAS_CXX20 1
#elif CPP_LANGUAGE_VERSION > 201402L // C++17 or higher
#define HAS_CXX17 1
#define HAS_CXX20 0
#elif CPP_LANGUAGE_VERSION > 201103L // C++14 or higher
#define HAS_CXX17 0
#define HAS_CXX20 0
#else // C++11 or lower
#error Squid::Tasks requires C++14 or higher
#define HAS_CXX17 0
#define HAS_CXX20 0
#endif
#undef CPP_LANGUAGE_VERSION
// C++20 Compatibility (std::coroutine)
#if HAS_CXX20 || (defined(_MSVC_LANG) && defined(__cpp_lib_coroutine)) // Standard coroutines
#include <coroutine>
#define SQUID_EXPERIMENTAL_COROUTINES 0
#else // Experimental coroutines
#if defined(__clang__) && defined(_STL_COMPILER_PREPROCESSOR)
// HACK: Some distributions of clang don't have a <experimental/coroutine> header. We only need a few symbols, so just define them ourselves
namespace std {
namespace experimental {
inline namespace coroutines_v1 {
template <typename R, typename...> struct coroutine_traits {
using promise_type = typename R::promise_type;
};
template <typename Promise = void> struct coroutine_handle;
template <> struct coroutine_handle<void> {
static coroutine_handle from_address(void* addr) noexcept {
coroutine_handle me;
me.ptr = addr;
return me;
}
void operator()() { resume(); }
void* address() const { return ptr; }
void resume() const { __builtin_coro_resume(ptr); }
void destroy() const { __builtin_coro_destroy(ptr); }
bool done() const { return __builtin_coro_done(ptr); }
coroutine_handle& operator=(decltype(nullptr)) {
ptr = nullptr;
return *this;
}
coroutine_handle(decltype(nullptr)) : ptr(nullptr) {}
coroutine_handle() : ptr(nullptr) {}
// void reset() { ptr = nullptr; } // add to P0057?
explicit operator bool() const { return ptr; }
protected:
void* ptr;
};
template <typename Promise> struct coroutine_handle : coroutine_handle<> {
using coroutine_handle<>::operator=;
static coroutine_handle from_address(void* addr) noexcept {
coroutine_handle me;
me.ptr = addr;
return me;
}
Promise& promise() const {
return *reinterpret_cast<Promise*>(
__builtin_coro_promise(ptr, alignof(Promise), false));
}
static coroutine_handle from_promise(Promise& promise) {
coroutine_handle p;
p.ptr = __builtin_coro_promise(&promise, alignof(Promise), true);
return p;
}
};
template <typename _PromiseT>
bool operator==(coroutine_handle<_PromiseT> const& _Left,
coroutine_handle<_PromiseT> const& _Right) noexcept
{
return _Left.address() == _Right.address();
}
template <typename _PromiseT>
bool operator!=(coroutine_handle<_PromiseT> const& _Left,
coroutine_handle<_PromiseT> const& _Right) noexcept
{
return !(_Left == _Right);
}
struct suspend_always {
bool await_ready() noexcept { return false; }
void await_suspend(coroutine_handle<>) noexcept {}
void await_resume() noexcept {}
};
struct suspend_never {
bool await_ready() noexcept { return true; }
void await_suspend(coroutine_handle<>) noexcept {}
void await_resume() noexcept {}
};
}
}
}
#else
#include <experimental/coroutine>
#endif
namespace std // Alias experimental coroutine symbols into std namespace
{
template <class _Promise = void>
using coroutine_handle = experimental::coroutine_handle<_Promise>;
using suspend_never = experimental::suspend_never;
using suspend_always = experimental::suspend_always;
};
#define SQUID_EXPERIMENTAL_COROUTINES 1
#endif
// Determine whether our tasks need the member function "unhandled_exception()" defined or not
#if defined(_MSC_VER)
// MSVC's rules for exceptions differ between standard + experimental coroutines
#if SQUID_EXPERIMENTAL_COROUTINES
// If exceptions are enabled, we must define unhandled_exception()
#if defined(__cpp_exceptions) && __cpp_exceptions == 199711
#define SQUID_NEEDS_UNHANDLED_EXCEPTION 1
#else
#define SQUID_NEEDS_UNHANDLED_EXCEPTION 0
#endif
#else
// If we're using VS16.11 or newer -- or older than 16.10, we have one set of rules for standard coroutines
#if _MSC_FULL_VER >= 192930133L || _MSC_VER < 1429L
#define SQUID_NEEDS_UNHANDLED_EXCEPTION 1
#else
#if defined(__cpp_exceptions) && __cpp_exceptions == 199711
#define SQUID_NEEDS_UNHANDLED_EXCEPTION 1
#else
// 16.10 has a bug with their standard coroutine implementation that creates a set of contradicting requirements
// https://developercommunity.visualstudio.com/t/coroutine-uses-promise_type::unhandled_e/1374530
#error Visual Studio 16.10 has a compiler bug that prevents all coroutines from compiling when exceptions are disabled and using standard C++20 coroutines or /await:strict. Please either upgrade your version of Visual Studio, or use the experimental /await flag, or enable exceptions.
#endif
#endif
#endif
#else
// Clang always requires unhandled_exception() to be defined
#define SQUID_NEEDS_UNHANDLED_EXCEPTION 1
#endif
// C++17 Compatibility ([[nodiscard]])
#if !defined(SQUID_NODISCARD) && defined(__has_cpp_attribute)
#if __has_cpp_attribute(nodiscard)
#define SQUID_NODISCARD [[nodiscard]]
#endif
#endif
#ifndef SQUID_NODISCARD
#define SQUID_NODISCARD
#endif
#undef HAS_CXX17
#undef HAS_CXX20
// Include UE core headers
#include "CoreMinimal.h"
#include "Engine/World.h"
#include "Engine/Engine.h"
#include "Async/Future.h"

1153
include/Task.h Normal file

File diff suppressed because it is too large Load Diff

331
include/TaskFSM.h Normal file
View File

@ -0,0 +1,331 @@
#pragma once
/// @defgroup TaskFSM Task FSM
/// @brief Finite state machine that implements states using task factories
/// @{
///
/// Full documentation of the TaskFSM system coming soon!
#include "Task.h"
NAMESPACE_SQUID_BEGIN
class TaskFSM;
namespace FSM
{
// State ID wrapper
struct StateId
{
StateId() = default;
StateId(int32_t in_idx) : idx(in_idx) {}
StateId(size_t in_idx) : idx((int32_t)in_idx) {}
bool operator==(const StateId& other) const { return (other.idx == idx); }
bool operator!=(const StateId& other) const { return (other.idx != idx); }
bool IsValid() const { return idx != INT32_MAX; }
int32_t idx = INT32_MAX; // Default to invalid idx
};
// State transition debug data
struct TransitionDebugData
{
FSM::StateId oldStateId;
FString oldStateName;
FSM::StateId newStateId;
FString newStateName;
};
// State transition callback function
using tOnStateTransitionFn = TFunction<void()>;
#include "Private/TaskFSMPrivate.h" // Internal use only! Do not include elsewhere!
//--- State Handle ---//
template<class tStateInput, class tStateConstructorFn>
class StateHandle
{
using tPredicateRet = typename std::conditional<!std::is_void<tStateInput>::value, TOptional<tStateInput>, bool>::type;
using tPredicateFn = TFunction<tPredicateRet()>;
public:
StateHandle(StateHandle&& in_other) = default;
StateHandle& operator=(StateHandle&& in_other) = default;
StateId GetId() const //< Get the ID of this state
{
return m_state ? m_state->idx : StateId{};
}
// SFINAE Template Declaration Macros (#defines)
/// @cond
#define NONVOID_ONLY_WITH_PREDICATE template <class tPredicateFn, typename tPayload = tStateInput, typename std::enable_if_t<!std::is_void<tPayload>::value>* = nullptr>
#define VOID_ONLY_WITH_PREDICATE template <class tPredicateFn, typename tPayload = tStateInput, typename std::enable_if_t<std::is_void<tPayload>::value>* = nullptr>
#define NONVOID_ONLY template <typename tPayload = tStateInput, typename std::enable_if_t<!std::is_void<tPayload>::value && !std::is_convertible<tPayload, tPredicateFn>::value>* = nullptr>
#define VOID_ONLY template <typename tPayload = tStateInput, typename std::enable_if_t<std::is_void<tPayload>::value>* = nullptr>
#define PREDICATE_ONLY template <typename tPredicateFn, typename std::enable_if_t<!std::is_convertible<tStateInput, tPredicateFn>::value>* = nullptr>
/// @endcond
// Link methods
VOID_ONLY LinkHandle Link() //< Empty predicate link (always follow link)
{
return _InternalLink([] { return true; }, LinkHandle::eType::Normal);
}
NONVOID_ONLY LinkHandle Link(tPayload in_payload) //< Empty predicate link w/ payload (always follow link, using provided payload)
{
return _InternalLink([payload = MoveTemp(in_payload)]() -> tPredicateRet { return payload; }, LinkHandle::eType::Normal);
}
PREDICATE_ONLY LinkHandle Link(tPredicateFn in_predicate) //< Predicate link w/ implicit payload (follow link when predicate returns a value; use return value as payload)
{
return _InternalLink(in_predicate, LinkHandle::eType::Normal);
}
NONVOID_ONLY_WITH_PREDICATE LinkHandle Link(tPredicateFn in_predicate, tPayload in_payload) //< Predicate link w/ explicit payload (follow link when predicate returns true; use provided payload)
{
return _InternalLink(in_predicate, MoveTemp(in_payload), LinkHandle::eType::Normal);
}
// OnCompleteLink methods
VOID_ONLY LinkHandle OnCompleteLink() //< Empty predicate link (always follow link)
{
return _InternalLink([] { return true; }, LinkHandle::eType::OnComplete);
}
NONVOID_ONLY LinkHandle OnCompleteLink(tPayload in_payload) //< Empty predicate link w/ payload (always follow link, using provided payload)
{
return _InternalLink([payload = MoveTemp(in_payload)]() -> tPredicateRet { return payload; }, LinkHandle::eType::OnComplete);
}
PREDICATE_ONLY LinkHandle OnCompleteLink(tPredicateFn in_predicate) //< Predicate link w/ implicit payload (follow link when predicate returns a value; use return value as payload)
{
return _InternalLink(in_predicate, LinkHandle::eType::OnComplete, true);
}
NONVOID_ONLY_WITH_PREDICATE LinkHandle OnCompleteLink(tPredicateFn in_predicate, tPayload in_payload) //< Predicate link w/ explicit payload (follow link when predicate returns true; use provided payload)
{
return _InternalLink(in_predicate, MoveTemp(in_payload), LinkHandle::eType::OnComplete, true);
}
private:
friend class ::TaskFSM;
StateHandle() = delete;
StateHandle(TSharedPtr<State<tStateInput, tStateConstructorFn>> InStatePtr)
: m_state(InStatePtr)
{
}
StateHandle(const StateHandle& Other) = delete;
StateHandle& operator=(const StateHandle& Other) = delete;
// Internal link function implementations
VOID_ONLY_WITH_PREDICATE LinkHandle _InternalLink(tPredicateFn in_predicate, LinkHandle::eType in_linkType, bool in_isConditional = false) // bool-returning predicate
{
static_assert(std::is_same<bool, decltype(in_predicate())>::value, "This link requires a predicate function returning bool");
TSharedPtr<LinkBase> link = MakeShared<FSM::Link<tStateInput, tStateConstructorFn, tPredicateFn>>(m_state, in_predicate);
return LinkHandle(link, in_linkType, in_isConditional);
}
NONVOID_ONLY_WITH_PREDICATE LinkHandle _InternalLink(tPredicateFn in_predicate, LinkHandle::eType in_linkType, bool in_isConditional = false) // optional-returning predicate
{
static_assert(std::is_same<TOptional<tStateInput>, decltype(in_predicate())>::value, "This link requires a predicate function returning TOptional<tStateInput>");
TSharedPtr<LinkBase> link = MakeShared<FSM::Link<tStateInput, tStateConstructorFn, tPredicateFn>>(m_state, in_predicate);
return LinkHandle(link, in_linkType, in_isConditional);
}
NONVOID_ONLY_WITH_PREDICATE LinkHandle _InternalLink(tPredicateFn in_predicate, tPayload in_payload, LinkHandle::eType in_linkType, bool in_isConditional = false) // bool-returning predicate w/ fixed payload
{
static_assert(std::is_same<bool, decltype(in_predicate())>::value, "This link requires a predicate function returning bool");
auto predicate = [in_predicate, in_payload]() -> TOptional<tStateInput>
{
return in_predicate() ? TOptional<tStateInput>(in_payload) : TOptional<tStateInput>{};
};
return _InternalLink(predicate, in_linkType, in_isConditional);
}
// SFINAE Template Declaration Macros (#undefs)
#undef NONVOID_ONLY_WITH_PREDICATE
#undef VOID_ONLY_WITH_PREDICATE
#undef NONVOID_ONLY
#undef VOID_ONLY
#undef PREDICATE_ONLY
TSharedPtr<State<tStateInput, tStateConstructorFn>> m_state; // Internal state object
};
} // namespace FSM
using StateId = FSM::StateId;
template<class tStateInput, class tStateConstructorFn>
using StateHandle = FSM::StateHandle<tStateInput, tStateConstructorFn>;
using TransitionDebugData = FSM::TransitionDebugData;
using tOnStateTransitionFn = FSM::tOnStateTransitionFn;
//--- TaskFSM ---//
class TaskFSM
{
public:
using tOnStateTransitionFn = TFunction<void()>;
using tDebugStateTransitionFn = TFunction<void(TransitionDebugData)>;
// Create a new FSM state [fancy param-deducing version (hopefully) coming soon!]
template<typename tStateConstructorFn>
auto State(FString in_name, tStateConstructorFn in_stateCtorFn)
{
typedef FSM::function_traits<tStateConstructorFn> tFnTraits;
using tStateInput = typename tFnTraits::tArg;
const FSM::StateId newStateId = m_states.Num();
m_states.Add(InternalStateData(in_name));
auto state = MakeShared<FSM::State<tStateInput, tStateConstructorFn>>(MoveTemp(in_stateCtorFn), newStateId, in_name);
return FSM::StateHandle<tStateInput, tStateConstructorFn>{ state };
}
// Create a new FSM exit state (immediately terminates the FSM when executed)
FSM::StateHandle<void, void> State(FString in_name)
{
const FSM::StateId newStateId = m_states.Num();
m_states.Add(InternalStateData(in_name));
m_exitStates.Add(newStateId);
auto state = MakeShared<FSM::State<void, void>>(newStateId, in_name);
return FSM::StateHandle<void, void>{ state };
}
// Define the initial entry links into the state machine
void EntryLinks(TArray<FSM::LinkHandle> in_entryLinks);
// Define all outgoing links from a given state (may only be called once per state)
template<class tStateInput, class tStateConstructorFn>
void StateLinks(const FSM::StateHandle<tStateInput, tStateConstructorFn>& in_originState, TArray<FSM::LinkHandle> in_outgoingLinks);
// Begins execution of the state machine (returns id of final exit state)
Task<FSM::StateId> Run(tOnStateTransitionFn in_onTransitionFn = {}, tDebugStateTransitionFn in_debugStateTransitionFn = {}) const;
private:
// Evaluates all possible outgoing links from the current state, returning the first valid transition (if any transitions are valid)
TOptional<FSM::TransitionEvent> EvaluateLinks(FSM::StateId in_curStateId, bool in_isCurrentStateComplete, const tOnStateTransitionFn& in_onTransitionFn) const;
// Internal state
struct InternalStateData
{
InternalStateData(FString in_debugName)
: debugName(in_debugName)
{
}
TArray<FSM::LinkHandle> outgoingLinks;
FString debugName;
};
TArray<InternalStateData> m_states;
TArray<FSM::LinkHandle> m_entryLinks;
TArray<FSM::StateId> m_exitStates;
};
/// @} end of group TaskFSM
//--- TaskFSM Methods ---//
template<class tStateInput, class tStateConstructorFn>
void TaskFSM::StateLinks(const FSM::StateHandle<tStateInput, tStateConstructorFn>& in_originState, TArray<FSM::LinkHandle> in_outgoingLinks)
{
const int32_t stateIdx = in_originState.m_state->stateId.idx;
SQUID_RUNTIME_CHECK(m_states[stateIdx].outgoingLinks.Num() == 0, "Cannot set outgoing links more than once for each state");
// Validate that there are exactly 0 or 1 unconditional OnComplete links (there may be any number of other OnComplete links, but only one with no condition)
int32_t numOnCompleteLinks = 0;
int32_t numOnCompleteLinks_Unconditional = 0;
for(const FSM::LinkHandle& link : in_outgoingLinks)
{
if(link.IsOnCompleteLink())
{
SQUID_RUNTIME_CHECK(numOnCompleteLinks_Unconditional == 0, "Cannot call OnCompleteLink() after calling OnCompleteLink() with no conditions (unreachable link)");
++numOnCompleteLinks;
if(!link.HasCondition())
{
numOnCompleteLinks_Unconditional++;
}
}
}
SQUID_RUNTIME_CHECK(numOnCompleteLinks == 0 || numOnCompleteLinks_Unconditional > 0, "More than one unconditional OnCompleteLink() was set");
// Set the outgoing links for the origin state
m_states[stateIdx].outgoingLinks = MoveTemp(in_outgoingLinks);
}
inline void TaskFSM::EntryLinks(TArray<FSM::LinkHandle> in_entryLinks)
{
// Validate to ensure there are no OnComplete links set as entry links
int32_t numOnCompleteLinks = 0;
for(const FSM::LinkHandle& link : in_entryLinks)
{
if(link.IsOnCompleteLink())
{
++numOnCompleteLinks;
}
}
SQUID_RUNTIME_CHECK(numOnCompleteLinks == 0, "EntryLinks() list may not contain any OnCompleteLink() links");
// Set the entry links list for this FSM
m_entryLinks = MoveTemp(in_entryLinks);
}
inline TOptional<FSM::TransitionEvent> TaskFSM::EvaluateLinks(FSM::StateId in_curStateId, bool in_isCurrentStateComplete, const tOnStateTransitionFn& in_onTransitionFn) const
{
// Determine whether to use entry links or state-specific outgoing links
const TArray<FSM::LinkHandle>& links = (in_curStateId.idx < m_states.Num()) ? m_states[in_curStateId.idx].outgoingLinks : m_entryLinks;
// Find the first valid transition from the current state
for(const FSM::LinkHandle& link : links)
{
if(!link.IsOnCompleteLink() || in_isCurrentStateComplete) // Skip link evaluation check for OnComplete links unless current state is complete
{
if(auto result = link.EvaluateLink(in_onTransitionFn)) // Check if the transition to this state is valid
{
return result;
}
}
}
return {}; // No valid transition was found
}
inline Task<FSM::StateId> TaskFSM::Run(tOnStateTransitionFn in_onTransitionFn, tDebugStateTransitionFn in_debugStateTransitionFn) const
{
// Task-local variables
FSM::StateId curStateId; // The current state's ID
Task<> task; // The current state's task
// Custom debug task name logic
TASK_NAME(__FUNCTION__, [this, &curStateId, &task]
{
const auto stateName = m_states.IsValidIndex(curStateId.idx) ? m_states[curStateId.idx].debugName : "";
return FString::Printf(TEXT("%s -- %s"), *stateName, *task.GetDebugStack());
});
// Debug state transition lambda
auto DebugStateTransition = [this, in_debugStateTransitionFn](FSM::StateId in_oldStateId, FSM::StateId in_newStateId) {
if(in_debugStateTransitionFn)
{
FString oldStateName = in_oldStateId.IsValid() ? m_states[in_oldStateId.idx].debugName : FString("<ENTRY>");
FString newStateName = m_states[in_newStateId.idx].debugName;
in_debugStateTransitionFn({ in_oldStateId, MoveTemp(oldStateName), in_newStateId, MoveTemp(newStateName) });
}
};
// Main FSM loop
while(true)
{
// Evaluate links, checking for a valid transition
if(TOptional<FSM::TransitionEvent> transition = EvaluateLinks(curStateId, task.IsDone(), in_onTransitionFn))
{
auto newStateId = transition->newStateId;
DebugStateTransition(curStateId, newStateId); // Call state-transition debug function
// If the transition is to an exit state, return that state ID (terminating the FSM)
if(m_exitStates.Contains(newStateId.idx))
{
co_return newStateId;
}
SQUID_RUNTIME_CHECK(newStateId.idx < m_states.Num(), "It should be logically impossible to get an invalid state to this point");
// Begin running new state (implicitly killing old state)
curStateId = newStateId;
co_await RemoveStopTask(task);
task = MoveTemp(transition->newTask); // NOTE: Initial call to Resume() happens below
co_await AddStopTask(task);
}
// Resume current state
task.Resume();
// Suspend until next frame
co_await Suspend();
}
}
NAMESPACE_SQUID_END

215
include/TaskManager.h Normal file
View File

@ -0,0 +1,215 @@
#pragma once
/// @defgroup TaskManager Task Manager
/// @brief Manager that runs and resumes a collection of tasks.
/// @{
///
/// A TaskManager is a simple manager class that holds an ordered list of tasks and resumes them whenever it is updated.
///
/// Running Tasks
/// -------------
/// There are two primary ways to run tasks on a task manager.
///
/// The first method (running an "unmanaged task") is to pass a task into @ref TaskManager::Run(). This will move the task
/// into the task manager and return a @ref TaskHandle that can be used to observe and manage the lifetime of the task (as well
/// as potentially take a return value after the task finishes). With unmanaged tasks, the task manager only holds a weak
/// reference to the task, meaning that the @ref TaskHandle returned by @ref TaskManager::Run() is the only remaining strong
/// reference to the task. Because of this, the caller is entirely responsible for managing the lifetime of the task.
///
/// The second method (running a "managed task") is to pass a task into @ref TaskManager::RunManaged(). Like
/// @ref TaskManager::Run(), this will move the task into the task manager and return a @ref WeakTaskHandle that can be used to
/// observe the lifetime of the task (as well as manually kill it, if desired). Unlike unmanaged tasks, the task manager
/// stores a strong reference to the task. Because of this, that caller is not responsible for managing the lifetime of
/// the task. This difference in task ownership means that (unlike an unmanaged task) a managed task can be thought of as
/// a "fire-and-forget" task that will run until either it finishes or until something else explicitly kills it.
///
/// Order of Execution
/// ------------------
/// The ordering of task updates within a call to @ref TaskManager::Update() is stable, meaning that the first task that
/// is run on a task manager will remain the first to resume, no matter how many other tasks are run on the task manager
/// (or terminate) in the meantime.
///
/// Integration into Actor Classes
/// ------------------------------
/// Consider the following example of a TaskManager that has been integrated into a TaskActor base class:
///
/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
///
/// class TaskActor : public Actor
/// {
/// public:
/// virtual void OnInitialize() override // Automatically called when this enemy enters the scene
/// {
/// Actor::OnInitialize(); // Call the base Actor function
/// m_taskMgr.RunManaged(ManageActor()); // Run main actor task as a fire-and-forget "managed task"
/// }
///
/// virtual void Tick(float in_dt) override // Automatically called every frame
/// {
/// Actor::Tick(in_dt); // Call the base Actor function
/// m_taskMgr.Update(); // Resume all active tasks once per tick
/// }
///
/// virtual void OnDestroy() override // Automatically called when this enemy leaves the scene
/// {
/// m_taskMgr.KillAllTasks(); // Kill all active tasks when we leave the scene
/// Actor::OnDestroy(); // Call the base Actor function
/// }
///
/// protected:
/// virtual Task<> ManageActor() // Overridden (in its entirety) by child classes
/// {
/// co_await WaitForever(); // Waits forever (doing nothing)
/// }
///
/// TaskManager m_taskMgr;
/// };
///
/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
///
/// In the above example, TaskManager is instantiated once per high-level actor. It is updated once per frame within
/// the Tick() method, and all its tasks are killed when it leaves the scene in OnDestroy(). Lastly, a single entry-point
/// coroutine is run as a managed task when the actor enters the scene. (The above is the conventional method of integration
/// into this style of game engine.)
///
/// Note that it is sometimes necessary to have multiple TaskManagers within a single actor. For example, if there are
/// multiple tick functions (such as one for pre-physics updates and one for post-physics updates), then instantiating
/// a second "post-physics" task manager may be desirable.
#include "Task.h"
NAMESPACE_SQUID_BEGIN
//--- TaskManager ---//
/// Manager that runs and resumes a collection of tasks.
class TaskManager
{
public:
~TaskManager() {} /// Destructor (disables copy/move construction + assignment)
/// @brief Run an unmanaged task
/// @details Run() return a @ref TaskHandle<> that holds a strong reference to the task. If there are ever no
/// strong references remaining to an unmanaged task, it will immediately be killed and removed from the manager.
template <typename tRet>
SQUID_NODISCARD TaskHandle<tRet> Run(Task<tRet>&& in_task)
{
// Run unmanaged task
TaskHandle<tRet> taskHandle = in_task;
WeakTask weakTask = MoveTemp(in_task);
RunWeakTask(MoveTemp(weakTask));
return taskHandle;
}
template <typename tRet>
SQUID_NODISCARD TaskHandle<tRet> Run(const Task<tRet>& in_task) /// @private Illegal copy implementation
{
static_assert(static_false<tRet>::value, "Cannot run an unmanaged task by copy (try Run(MoveTemp(task)))");
return {};
}
/// @brief Run a managed task
/// @details RunManaged() return a @ref WeakTaskHandle, meaning it can be used to run a "fire-and-forget" background
/// task in situations where it is not necessary to observe or control task lifetime.
template <typename tRet>
WeakTaskHandle RunManaged(Task<tRet>&& in_task)
{
// Run managed task
WeakTaskHandle weakTaskHandle = in_task;
m_strongRefs.Add(Run(MoveTemp(in_task)));
return weakTaskHandle;
}
template <typename tRet>
WeakTaskHandle RunManaged(const Task<tRet>& in_task) /// @private Illegal copy implementation
{
static_assert(static_false<tRet>::value, "Cannot run a managed task by copy (try RunManaged(MoveTemp(task)))");
return {};
}
/// @brief Run a weak task
/// @details RunWeakTask() runs a WeakTask. The caller is assumed to have already created a strong TaskHandle<> that
/// references the WeakTask, thus keeping it from being killed. When the last strong reference to the WeakTask is
/// destroyed, the task will immediately be killed and removed from the manager.
void RunWeakTask(WeakTask&& in_task)
{
// Run unmanaged task
m_tasks.Add(MoveTemp(in_task));
}
/// Call Task::Kill() on all tasks (managed + unmanaged)
void KillAllTasks()
{
m_tasks.Reset(); // Destroying all the weak tasks implicitly destroys all internal tasks
// No need to call Kill() on each TaskHandle in m_strongRefs
m_strongRefs.Reset(); // Handles in the strong refs array only ever point to tasks in the now-cleared m_tasks array
}
/// @brief Issue a stop request using @ref Task::RequestStop() on all active tasks (managed and unmanaged)
/// @details Returns a new awaiter task that will wait until all those tasks have all terminated.
Task<> StopAllTasks()
{
// Request stop on all tasks
TArray<WeakTaskHandle> weakHandles;
for(auto& task : m_tasks)
{
task.RequestStop();
weakHandles.Add(task);
}
// Return a fence task that waits until all stopped tasks are complete
return [](TArray<WeakTaskHandle> in_weakHandles) -> Task<> {
TASK_NAME("StopAllTasks() Fence Task");
for(const auto& weakHandle : in_weakHandles)
{
co_await weakHandle; // Wait until task is complete
}
}(MoveTemp(weakHandles));
}
/// Call @ref Task::Resume() on all active tasks exactly once (managed + unmanaged)
void Update()
{
// Resume all tasks
int32 writeIdx = 0;
for(int32 readIdx = 0; readIdx < m_tasks.Num(); ++readIdx)
{
if(m_tasks[readIdx].Resume() != eTaskStatus::Done)
{
if(writeIdx != readIdx)
{
m_tasks[writeIdx] = MoveTemp(m_tasks[readIdx]);
}
++writeIdx;
}
}
m_tasks.SetNum(writeIdx);
// Prune strong tasks that are done
m_strongRefs.RemoveAllSwap([](const auto& in_taskHandle) { return in_taskHandle.IsDone(); });
}
/// Get a debug string containing a list of all active tasks
FString GetDebugString(TOptional<TaskDebugStackFormatter> in_formatter = {}) const
{
FString debugStr;
for(const auto& task : m_tasks)
{
if(!task.IsDone())
{
if(debugStr.Len())
{
debugStr += '\n';
}
debugStr += task.GetDebugStack(in_formatter);
}
}
return debugStr;
}
private:
TArray<WeakTask> m_tasks;
TArray<TaskHandle<>> m_strongRefs;
};
NAMESPACE_SQUID_END
///@} end of TaskManager group

48
include/TasksConfig.h Normal file
View File

@ -0,0 +1,48 @@
#pragma once
// Squid::Tasks version (major.minor.patch)
#define SQUID_TASKS_VERSION_MAJOR 0
#define SQUID_TASKS_VERSION_MINOR 2
#define SQUID_TASKS_VERSION_PATCH 0
/// @defgroup Config Configuration
/// @brief Configuration settings for the Squid::Tasks library
/// @{
/// Enables Task debug names and callstack tracking via Task::GetDebugStack() and Task::GetDebugName()
#ifndef SQUID_ENABLE_TASK_DEBUG
#define SQUID_ENABLE_TASK_DEBUG 1
#endif
/// Switches time type (tTaskTime) from 32-bit single-precision floats to 64-bit double-precision floats
#ifndef SQUID_ENABLE_DOUBLE_PRECISION_TIME
#define SQUID_ENABLE_DOUBLE_PRECISION_TIME 0
#endif
/// Wraps a Squid:: namespace around all classes in the Squid::Tasks library
#ifndef SQUID_ENABLE_NAMESPACE
#define SQUID_ENABLE_NAMESPACE 0
#endif
/// Enables experimental (largely-untested) exception handling, and replaces all asserts with runtime_error exceptions
#ifndef SQUID_USE_EXCEPTIONS
#define SQUID_USE_EXCEPTIONS 0
#endif
/// Enables global time support(alleviating the need to specify a time stream for time - sensitive awaiters) [see @ref GetGlobalTime()]
#ifndef SQUID_ENABLE_GLOBAL_TIME
// ***************
// *** WARNING ***
// ***************
// It is generally inadvisable for game projects to define a global task time, as it assumes there is only a single time-stream.
// Within game projects, there is usually a "game time" and "real time", as well as others (such as "audio time", "unpaused time").
// Furthermore, in engines such as Unreal, a non-static world context object must be provided.
// To enable global task time, user must *also* define a GetGlobalTime() implementation (otherwise there will be a linker error)
#define SQUID_ENABLE_GLOBAL_TIME 0
#endif
/// @} end of addtogroup Config
//--- C++17/C++20 Compatibility ---//
#include "Private/TasksCommonPrivate.h"

320
include/TokenList.h Normal file
View File

@ -0,0 +1,320 @@
#pragma once
/// @defgroup Tokens Token List
/// @brief Data structure for tracking decentralized state across multiple tasks.
/// @{
///
/// Token objects can be created using @ref TokenList::MakeToken(), returning a shared pointer to a new Token. This
/// new Token can then be added to the TokenList using @ref TokenList::AddToken(). @ref TokenList::TakeToken()
/// can be used to make + add a new token with a single function call.
///
/// Because TokenList uses weak pointers to track its elements, Token objects are logically removed from the list once
/// they are destroyed. As such, it is usually unnecessary to explicitly call @ref TokenList::RemoveToken() to remove a
/// Token from the list. Instead, it is idiomatic to consider the Token to be a sort of "scope guard" that will remove
/// itself from all TokenList objects when it leaves scope.
///
/// The TokenList class is included as part of Squid::Tasks to provide a simple mechanism for robustly sharing aribtrary
/// state between multiple tasks. Consider this example of a poison damage-over-time system:
/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
///
/// class Character : public Actor
/// {
/// public:
/// bool IsPoisoned() const
/// {
/// return m_poisonTokens; // Whether there are any live poison tokens
/// }
///
/// void OnPoisoned(float in_dps, float in_duration)
/// {
/// m_taskMgr.RunManaged(ManagePoisonInstance(in_dps, in_duration));
/// }
///
/// private:
/// TokenList<float> m_poisonTokens; // Token list indicating live poison damage
///
/// Task<> ManagePoisonInstance(float in_dps, float in_duration)
/// {
/// // Take a poison token and hold it for N seconds
/// auto poisonToken = m_poisonTokens.TakeToken(__FUNCTION__, in_dps);
/// co_await WaitSeconds(in_duration);
/// }
///
/// Task<> ManageCharacter() // Called once per frame
/// {
/// while(true)
/// {
/// float poisonDps = m_poisonTokens.GetMax(); // Get highest DPS poison instance
/// DealDamage(poisonDps * GetDT()); // Deal the actual poison damage
/// co_await Suspend();
/// }
/// }
/// };
///
/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
///
/// As the above example shows, this mechanism is well-suited for coroutines, as they can hold a Token across
/// multiple frames. Also note that Token objects can optionally hold data. The TokenList class has query functions
/// (e.g. GetMin()/GetMax()) that can be used to aggregate the data from the set of live tokens. This is used above
/// to quickly find the highest DPS poison instance.
#include <algorithm>
#include <numeric>
#include <vector>
#include <string>
//--- User configuration header ---//
#include "TasksConfig.h"
NAMESPACE_SQUID_BEGIN
template <typename T = void>
class TokenList;
/// @brief Handle to a TokenList element that stores a debug name
/// @details In most circumstances, name should be set to \ref __FUNCTION__ at the point of creation.
struct Token
{
Token(FString in_name)
: name(MoveTemp(in_name))
{
}
FString name; // Used for debug only
};
/// @brief Handle to a TokenList element that stores both a debug name and associated data
/// @details In most circumstances, name should be set to \c __FUNCTION__ at the point of creation.
template <typename tData>
struct DataToken
{
DataToken(FString in_name, tData in_data)
: name(MoveTemp(in_name))
, data(MoveTemp(in_data))
{
}
FString name; // Used for debug only
tData data;
};
/// Create a token with the specified debug name
inline TSharedPtr<Token> MakeToken(FString in_name)
{
return MakeShared<Token>(MoveTemp(in_name));
}
/// Create a token with the specified debug name and associated data
template <typename tData>
TSharedPtr<DataToken<tData>> MakeToken(FString in_name, tData in_data)
{
return MakeShared<DataToken<tData>>(MoveTemp(in_name), MoveTemp(in_data));
}
/// @brief Container for tracking decentralized state across multiple tasks. (See \ref Tokens for more info...)
/// @tparam T Type of data to associate with each Token in this container
template <typename T>
class TokenList
{
public:
/// Type of Token tracked by this container
using Token = typename std::conditional_t<std::is_void<T>::value, Token, DataToken<T>>;
/// Create a token with the specified debug name
template <typename U = T, typename std::enable_if_t<std::is_void<U>::value>* = nullptr>
static TSharedPtr<Token> MakeToken(FString in_name)
{
return MakeShared<Token>(MoveTemp(in_name));
}
/// Create a token with the specified debug name and associated data
template <typename U = T, typename std::enable_if_t<!std::is_void<U>::value>* = nullptr>
static TSharedPtr<Token> MakeToken(FString in_name, U in_data)
{
return MakeShared<Token>(MoveTemp(in_name), MoveTemp(in_data));
}
/// Create and add a token with the specified debug name
template <typename U = T, typename std::enable_if_t<std::is_void<U>::value>* = nullptr>
SQUID_NODISCARD TSharedPtr<Token> TakeToken(FString in_name)
{
return AddToken(MakeToken(MoveTemp(in_name)));
}
/// Create and add a token with the specified debug name and associated data
template <typename U = T, typename std::enable_if_t<!std::is_void<U>::value>* = nullptr>
SQUID_NODISCARD TSharedPtr<Token> TakeToken(FString in_name, U in_data)
{
return AddToken(MakeToken(MoveTemp(in_name), MoveTemp(in_data)));
}
/// Add an existing token to this container
TSharedPtr<Token> AddToken(TSharedPtr<Token> in_token)
{
SQUID_RUNTIME_CHECK(in_token, "Cannot add null token");
Sanitize();
m_tokens.AddUnique(in_token);
return in_token;
}
/// Explicitly remove a token from this container
void RemoveToken(TSharedPtr<Token> in_token)
{
// Find and remove the token
m_tokens.Remove(in_token);
}
/// Convenience conversion operator that calls HasTokens()
operator bool() const
{
return HasTokens();
}
/// Returns whether this container holds any live tokens
bool HasTokens() const
{
// Return true when holding any unexpired tokens
for(auto i = (int32_t)(m_tokens.Num() - 1); i >= 0; --i)
{
const auto& token = m_tokens[i];
if(token.IsValid())
{
return true;
}
m_tokens.Pop(); // Because the token is expired, we can safely remove it from the back
}
return false;
}
/// Returns an array of all live token data
TArray<T> GetTokenData() const
{
TArray<T> tokenData;
for(const auto& tokenWeak : m_tokens)
{
if(auto token = tokenWeak.Pin())
{
tokenData.Add(token->data);
}
}
return tokenData;
}
/// @name Data Queries
/// Methods for querying and aggregating the data from the set of live tokens.
/// @{
/// Returns associated data from the least-recently-added live token
TOptional<T> GetLeastRecent() const
{
Sanitize();
return m_tokens.Num() ? m_tokens[0].Pin()->data : TOptional<T>{};
}
/// Returns associated data from the most-recently-added live token
TOptional<T> GetMostRecent() const
{
Sanitize();
return m_tokens.Num() ? m_tokens.Last().Pin()->data : TOptional<T>{};
}
/// Returns smallest associated data from the set of live tokens
TOptional<T> GetMin() const
{
TOptional<T> ret;
SanitizeAndProcessData([&ret](const T& in_data) {
if(!ret || in_data < ret.GetValue())
{
ret = in_data;
}
});
return ret;
}
/// Returns largest associated data from the set of live tokens
TOptional<T> GetMax() const
{
TOptional<T> ret;
SanitizeAndProcessData([&ret](const T& in_data) {
if(!ret || in_data > ret.GetValue())
{
ret = in_data;
}
});
return ret;
}
/// Returns arithmetic mean of all associated data from the set of live tokens
TOptional<double> GetMean() const
{
TOptional<double> ret;
TOptional<double> total;
SanitizeAndProcessData([&total](const T& in_data) {
total = total.Get(0.0) + (double)in_data;
});
if(total)
{
ret = total.GetValue() / m_tokens.Num();
}
return ret;
}
/// Returns whether the set of live tokens contains at least one token associated with the specified data
template <typename U = T, typename std::enable_if_t<!std::is_void<U>::value>* = nullptr>
bool Contains(const U& in_searchData) const
{
bool containsData = false;
SanitizeAndProcessData([&in_searchData, &containsData](const T& in_data) {
if(in_searchData == in_data)
{
containsData = true;
}
});
return containsData;
}
///@} end of Data Queries
/// Returns a debug string containing a list of the debug names of all live tokens
FString GetDebugString() const
{
TArray<FString> tokenStrings;
for(auto token : m_tokens)
{
if(token.IsValid())
{
tokenStrings.Add(token.Pin()->name);
}
}
if(tokenStrings.Num())
{
return FString::Join(tokenStrings, TEXT("\n"));
}
return TEXT("[no tokens]");
}
private:
// Sanitation
void Sanitize() const
{
// Remove all invalid tokens
m_tokens.RemoveAll([](const Wp<Token>& in_token) { return !in_token.IsValid(); });
}
template <typename tFn>
void SanitizeAndProcessData(tFn in_dataFn) const
{
// Remove all invalid tokens while applying a processing function on each valid token
m_tokens.RemoveAll([&in_dataFn](const TWeakPtr<Token>& in_token) {
if(auto pinnedToken = in_token.Pin())
{
in_dataFn(pinnedToken->data);
return false;
}
return true;
});
}
// Token data
mutable TArray<TWeakPtr<Token>> m_tokens; // Mutable so we can remove expired tokens while converting bool
};
NAMESPACE_SQUID_END
///@} end of Tokens group

View File

@ -0,0 +1,52 @@
#pragma once
#include <chrono>
#include <atomic>
//--- Time System ---//
class TimeSystem
{
public:
template <typename... Args>
static void Create(Args&&... args)
{
s_timeSys = new TimeSystem(std::forward<Args>(args)...);
}
static void UpdateTime()
{
s_timeSys->_UpdateTime();
}
static auto GetTimeSince(double in_time)
{
return s_timeSys->_GetTimeSince(in_time);
}
static auto GetTime()
{
return s_timeSys->_GetTime();
}
private:
TimeSystem()
{
m_startTimePoint = std::chrono::steady_clock::now();
}
void _UpdateTime()
{
std::chrono::steady_clock::time_point curTimePoint = std::chrono::steady_clock::now();
std::chrono::duration<double> span = std::chrono::duration_cast<std::chrono::duration<double>>(curTimePoint - m_startTimePoint);
m_time = span.count();
}
double _GetTimeSince(double in_time) const
{
return m_time - in_time;
}
double _GetTime() const
{
return m_time;
}
std::chrono::steady_clock::time_point m_startTimePoint;
std::atomic<double> m_time;
static TimeSystem* s_timeSys;
};
TimeSystem* TimeSystem::s_timeSys;

View File

@ -0,0 +1,32 @@
#include "Task.h"
#include "TaskManager.h"
#include "TimeSystem.h"
// User-defined GetGlobalTime() is required to link Task.h
NAMESPACE_SQUID_BEGIN
tTaskTime GetGlobalTime()
{
return (tTaskTime)TimeSystem::GetTime();
}
NAMESPACE_SQUID_END
// Simple main function
int main(int argc, char** argv)
{
TimeSystem::Create();
// Initialize the game
// ... <your code here> ...
// Run the game until it's ready to quit
while(true)
{
// Update time before each frame (logically, all tasks should resume "at the same time")
TimeSystem::UpdateTime();
// Update the game
// ... <your code here> ...
}
return 0;
}

View File

@ -0,0 +1,172 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Main.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\include\FunctionGuard.h" />
<ClInclude Include="..\..\include\Private\TasksCommonPrivate.h" />
<ClInclude Include="..\..\include\Private\TaskFSMPrivate.h" />
<ClInclude Include="..\..\include\Private\TaskPrivate.h" />
<ClInclude Include="..\..\include\Task.h" />
<ClInclude Include="..\..\include\TaskFSM.h" />
<ClInclude Include="..\..\include\TaskManager.h" />
<ClInclude Include="..\..\include\TasksConfig.h" />
<ClInclude Include="..\..\include\TokenList.h" />
<ClInclude Include="..\Common\TimeSystem.h" />
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{E48F8265-C836-4564-9525-AFB12295CF64}</ProjectGuid>
<RootNamespace>Sample_Template</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<ProjectName>Sample_Template</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions);SQUIDTASK_TIME_PRECISION_DOUBLE</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>Default</LanguageStandard>
<AdditionalOptions>/await -Xclang -fcoroutines-ts %(AdditionalOptions)</AdditionalOptions>
<AdditionalIncludeDirectories>../../include;../Common</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);SQUIDTASK_TIME_PRECISION_DOUBLE</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>Default</LanguageStandard>
<AdditionalOptions>/await -Xclang -fcoroutines-ts %(AdditionalOptions)</AdditionalOptions>
<AdditionalIncludeDirectories>../../include;../Common</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions);SQUIDTASK_TIME_PRECISION_DOUBLE</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>Default</LanguageStandard>
<AdditionalOptions>/await -Xclang -fcoroutines-ts %(AdditionalOptions)</AdditionalOptions>
<AdditionalIncludeDirectories>../../include;../Common</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions);SQUIDTASK_TIME_PRECISION_DOUBLE</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>Default</LanguageStandard>
<AdditionalOptions>/await -Xclang -fcoroutines-ts %(AdditionalOptions)</AdditionalOptions>
<AdditionalIncludeDirectories>../../include;../Common</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
<Filter Include="Source Files\SquidTasks">
<UniqueIdentifier>{63b632a7-ce3c-4dd9-a970-5e661d591932}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\SquidTasks\Private">
<UniqueIdentifier>{89a92d2a-3fa9-4c0d-8dbf-466c03830dc3}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\Common">
<UniqueIdentifier>{cf5b02a9-ec31-44ea-9840-80634ce22458}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\include\FunctionGuard.h">
<Filter>Source Files\SquidTasks</Filter>
</ClInclude>
<ClInclude Include="..\..\include\Task.h">
<Filter>Source Files\SquidTasks</Filter>
</ClInclude>
<ClInclude Include="..\..\include\TaskManager.h">
<Filter>Source Files\SquidTasks</Filter>
</ClInclude>
<ClInclude Include="..\..\include\TasksConfig.h">
<Filter>Source Files\SquidTasks</Filter>
</ClInclude>
<ClInclude Include="..\..\include\TokenList.h">
<Filter>Source Files\SquidTasks</Filter>
</ClInclude>
<ClInclude Include="..\..\include\TaskFSM.h">
<Filter>Source Files\SquidTasks</Filter>
</ClInclude>
<ClInclude Include="..\..\include\Private\TaskFSMPrivate.h">
<Filter>Source Files\SquidTasks\Private</Filter>
</ClInclude>
<ClInclude Include="..\..\include\Private\TaskPrivate.h">
<Filter>Source Files\SquidTasks\Private</Filter>
</ClInclude>
<ClInclude Include="..\..\include\Private\TasksCommonPrivate.h">
<Filter>Source Files\SquidTasks\Private</Filter>
</ClInclude>
<ClInclude Include="..\Common\TimeSystem.h">
<Filter>Source Files\Common</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -0,0 +1,83 @@
#include "Task.h"
#include "TimeSystem.h"
#include "TaskFSM.h"
// User-defined GetGlobalTime() is required to link Task.h
NAMESPACE_SQUID_BEGIN
tTaskTime GetGlobalTime()
{
return (tTaskTime)TimeSystem::GetTime();
}
NAMESPACE_SQUID_END
Task<> IdleTask()
{
TASK_NAME(__FUNCTION__);
printf("Idle task\n");
co_await WaitForever();
}
Task<> PeriodicTask(float in_duration)
{
TASK_NAME(__FUNCTION__);
printf("Periodic task\n");
co_await WaitSeconds(in_duration);
}
Task<> TestFsmTask()
{
TASK_NAME(__FUNCTION__);
TaskFSM fsm;
auto LambdaStateTask = [](float in_duration) -> Task<>
{
TASK_NAME(__FUNCTION__);
printf("Lambda state!\n");
auto stopCtx = co_await GetStopContext();
co_await WaitSeconds(in_duration).CancelIf([&] { return stopCtx.IsStopRequested(); });
};
auto idleState = fsm.State("Idle", IdleTask);
auto periodicState = fsm.State("Periodic", &PeriodicTask);
auto lambdaState = fsm.State("Lambda", LambdaStateTask);
auto endState = fsm.State("End");
fsm.EntryLinks({
idleState.Link(),
});
fsm.StateLinks(idleState, {
periodicState.Link([]() -> std::optional<float> { return 1.0f; }),
endState.OnCompleteLink(),
});
fsm.StateLinks(periodicState, {
lambdaState.Link([]() -> std::optional<float> { return 2.0f; }),
});
fsm.StateLinks(lambdaState, {
idleState.OnCompleteLink(),
});
auto fsmTask = fsm.Run();
fsmTask.RequestStop();
co_await std::move(fsmTask);
}
void TestTaskFSM()
{
auto task = TestFsmTask();
while(task.Resume() != eTaskStatus::Done)
{
TimeSystem::UpdateTime(); // Update time before each frame (logically, all tasks should resume "at the same time")
}
}
// Simple main function
int main(int argc, char** argv)
{
TimeSystem::Create();
TestTaskFSM();
return 0;
}

View File

@ -0,0 +1,172 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Main.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\include\FunctionGuard.h" />
<ClInclude Include="..\..\include\Private\TasksCommonPrivate.h" />
<ClInclude Include="..\..\include\Private\TaskFSMPrivate.h" />
<ClInclude Include="..\..\include\Private\TaskPrivate.h" />
<ClInclude Include="..\..\include\Task.h" />
<ClInclude Include="..\..\include\TaskFSM.h" />
<ClInclude Include="..\..\include\TaskManager.h" />
<ClInclude Include="..\..\include\TasksConfig.h" />
<ClInclude Include="..\..\include\TokenList.h" />
<ClInclude Include="..\Common\TimeSystem.h" />
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{ABA88D0D-D79F-4371-BA63-D441662242B4}</ProjectGuid>
<RootNamespace>Sample_Tests</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<ProjectName>Sample_Tests</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions);SQUIDTASK_TIME_PRECISION_DOUBLE</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>Default</LanguageStandard>
<AdditionalOptions>/await -Xclang -fcoroutines-ts %(AdditionalOptions)</AdditionalOptions>
<AdditionalIncludeDirectories>../../include;../Common</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);SQUIDTASK_TIME_PRECISION_DOUBLE</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>Default</LanguageStandard>
<AdditionalOptions>/await -Xclang -fcoroutines-ts %(AdditionalOptions)</AdditionalOptions>
<AdditionalIncludeDirectories>../../include;../Common</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions);SQUIDTASK_TIME_PRECISION_DOUBLE</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>Default</LanguageStandard>
<AdditionalOptions>/await -Xclang -fcoroutines-ts %(AdditionalOptions)</AdditionalOptions>
<AdditionalIncludeDirectories>../../include;../Common</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions);SQUIDTASK_TIME_PRECISION_DOUBLE</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>Default</LanguageStandard>
<AdditionalOptions>/await -Xclang -fcoroutines-ts %(AdditionalOptions)</AdditionalOptions>
<AdditionalIncludeDirectories>../../include;../Common</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
<Filter Include="Source Files\SquidTasks">
<UniqueIdentifier>{63b632a7-ce3c-4dd9-a970-5e661d591932}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\SquidTasks\Private">
<UniqueIdentifier>{89a92d2a-3fa9-4c0d-8dbf-466c03830dc3}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\Common">
<UniqueIdentifier>{cf5b02a9-ec31-44ea-9840-80634ce22458}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\include\FunctionGuard.h">
<Filter>Source Files\SquidTasks</Filter>
</ClInclude>
<ClInclude Include="..\..\include\Task.h">
<Filter>Source Files\SquidTasks</Filter>
</ClInclude>
<ClInclude Include="..\..\include\TaskManager.h">
<Filter>Source Files\SquidTasks</Filter>
</ClInclude>
<ClInclude Include="..\..\include\TasksConfig.h">
<Filter>Source Files\SquidTasks</Filter>
</ClInclude>
<ClInclude Include="..\..\include\TokenList.h">
<Filter>Source Files\SquidTasks</Filter>
</ClInclude>
<ClInclude Include="..\..\include\TaskFSM.h">
<Filter>Source Files\SquidTasks</Filter>
</ClInclude>
<ClInclude Include="..\..\include\Private\TaskFSMPrivate.h">
<Filter>Source Files\SquidTasks\Private</Filter>
</ClInclude>
<ClInclude Include="..\..\include\Private\TaskPrivate.h">
<Filter>Source Files\SquidTasks\Private</Filter>
</ClInclude>
<ClInclude Include="..\..\include\Private\TasksCommonPrivate.h">
<Filter>Source Files\SquidTasks\Private</Filter>
</ClInclude>
<ClInclude Include="..\Common\TimeSystem.h">
<Filter>Source Files\Common</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -0,0 +1,27 @@
#include "Task.h"
#include "TimeSystem.h"
#include "TextGame.h"
#include "TaskFSM.h"
// User-defined GetGlobalTime() is required to link Task.h
NAMESPACE_SQUID_BEGIN
tTaskTime GetGlobalTime()
{
return (tTaskTime)TimeSystem::GetTime();
}
NAMESPACE_SQUID_END
// Simple main function
int main(int argc, char** argv)
{
TimeSystem::Create();
auto game = std::make_shared<TextGame>();
while(!game->IsGameOver())
{
TimeSystem::UpdateTime(); // Update time before each frame (logically, all tasks should resume "at the same time")
game->Update();
}
return 0;
}

View File

@ -0,0 +1,174 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Main.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\include\FunctionGuard.h" />
<ClInclude Include="..\..\include\Private\TasksCommonPrivate.h" />
<ClInclude Include="..\..\include\Private\TaskFSMPrivate.h" />
<ClInclude Include="..\..\include\Private\TaskPrivate.h" />
<ClInclude Include="..\..\include\Task.h" />
<ClInclude Include="..\..\include\TaskFSM.h" />
<ClInclude Include="..\..\include\TaskManager.h" />
<ClInclude Include="..\..\include\TasksConfig.h" />
<ClInclude Include="..\..\include\TokenList.h" />
<ClInclude Include="..\Common\TimeSystem.h" />
<ClInclude Include="TextGame.h" />
<ClInclude Include="TextInput.h" />
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{9095cb85-e1b0-4d03-9a3c-b3d277a1e300}</ProjectGuid>
<RootNamespace>Sample_TextGame</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<ProjectName>Sample_TextGame</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions);SQUIDTASK_TIME_PRECISION_DOUBLE</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>Default</LanguageStandard>
<AdditionalOptions>/await:strict -Xclang -fcoroutines-ts </AdditionalOptions>
<AdditionalIncludeDirectories>../../include;../Common</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);SQUIDTASK_TIME_PRECISION_DOUBLE</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>Default</LanguageStandard>
<AdditionalOptions>/await:strict -Xclang -fcoroutines-ts </AdditionalOptions>
<AdditionalIncludeDirectories>../../include;../Common</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions);SQUIDTASK_TIME_PRECISION_DOUBLE</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp14</LanguageStandard>
<AdditionalOptions>/await -Xclang -fcoroutines-ts </AdditionalOptions>
<AdditionalIncludeDirectories>../../include;../Common</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions);SQUIDTASK_TIME_PRECISION_DOUBLE</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>Default</LanguageStandard>
<AdditionalOptions>/await:strict -Xclang -fcoroutines-ts </AdditionalOptions>
<AdditionalIncludeDirectories>../../include;../Common</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,69 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
<Filter Include="Source Files\SquidTasks">
<UniqueIdentifier>{63b632a7-ce3c-4dd9-a970-5e661d591932}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\SquidTasks\Private">
<UniqueIdentifier>{0b6b681b-d03c-436c-9a7b-f544d0845b52}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\Common">
<UniqueIdentifier>{a0b32634-d0f3-491e-a37a-66c739f881e5}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="TextInput.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="TextGame.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="..\..\include\FunctionGuard.h">
<Filter>Source Files\SquidTasks</Filter>
</ClInclude>
<ClInclude Include="..\..\include\Task.h">
<Filter>Source Files\SquidTasks</Filter>
</ClInclude>
<ClInclude Include="..\..\include\TaskManager.h">
<Filter>Source Files\SquidTasks</Filter>
</ClInclude>
<ClInclude Include="..\..\include\TasksConfig.h">
<Filter>Source Files\SquidTasks</Filter>
</ClInclude>
<ClInclude Include="..\..\include\TokenList.h">
<Filter>Source Files\SquidTasks</Filter>
</ClInclude>
<ClInclude Include="..\..\include\TaskFSM.h">
<Filter>Source Files\SquidTasks</Filter>
</ClInclude>
<ClInclude Include="..\..\include\Private\TaskFSMPrivate.h">
<Filter>Source Files\SquidTasks\Private</Filter>
</ClInclude>
<ClInclude Include="..\..\include\Private\TaskPrivate.h">
<Filter>Source Files\SquidTasks\Private</Filter>
</ClInclude>
<ClInclude Include="..\..\include\Private\TasksCommonPrivate.h">
<Filter>Source Files\SquidTasks\Private</Filter>
</ClInclude>
<ClInclude Include="..\Common\TimeSystem.h">
<Filter>Source Files\Common</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,124 @@
#pragma once
#include "Task.h"
#include <thread>
#include <string>
#include <iostream>
#include <list>
#include <conio.h>
using namespace Squid;
class TextInput
{
public:
TextInput()
{
m_inputThread = std::thread([this] {
InputThread();
});
}
~TextInput()
{
m_terminate = true;
m_inputThread.join();
}
void ClearInput()
{
std::lock_guard<std::mutex> inputLock(m_inputMutex);
m_inputStr.Reset();
}
Task<FString> WaitForInput(bool in_echoText = true)
{
TASK_NAME(__FUNCTION__);
ClearInput();
FString input;
while(true)
{
auto inputMaybe = GetNextInputChar();
if(inputMaybe)
{
auto c = inputMaybe.GetValue();
if(isalnum(c) || c == 32)
{
if(in_echoText)
{
std::cout << c;
}
input += c;
}
else if(c == 8) // Backspace
{
std::cout << c << ' ' << c;
input = input.substr(0, input.Num() - 1);
}
else if(c == '\r')
{
if(in_echoText)
{
std::cout << std::endl;
}
break;
}
}
co_await Suspend();
}
co_return input;
}
Task<char> WaitForInputChar()
{
TASK_NAME(__FUNCTION__);
ClearInput();
while(true)
{
auto inputMaybe = GetNextInputChar();
if(inputMaybe)
{
auto c = inputMaybe.GetValue();
if(isalnum(c) || c == 32 || c == 8 || c == '\r')
{
co_return c;
}
}
co_await Suspend();
}
co_return '\0';
}
private:
std::thread m_inputThread;
bool m_terminate = false;
std::mutex m_inputMutex;
std::list<char> m_inputStr;
TOptional<char> GetNextInputChar()
{
std::lock_guard<std::mutex> inputLock(m_inputMutex);
if(m_inputStr.Num())
{
char c = m_inputStr.front();
m_inputStr.pop_front();
return c;
}
return {};
}
void InputThread()
{
while(!m_terminate)
{
if(_kbhit())
{
char c = _getch();
{
std::lock_guard<std::mutex> inputLock(m_inputMutex);
m_inputStr.Add(c);
}
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}
}
};

View File

@ -0,0 +1,623 @@
abandon abdicate, desert, leave, resign, abjure, discontinue, quit, retire from, cast off, forego, recant, retract, cease, forsake, relinquish, surrender, cede, forswear, renounce, vacate, depart from, give up, repudiate, withdraw from adopt, defend, occupy, seek, advocate, favor, prosecute, support, assert, haunt, protect, undertake, cherish, hold, pursue, uphold, claim, keep, retain, vindicate, court, maintain
abase bring low, depress, dishonor, lower, cast down, discredit, humble, reduce, debase, disgrace, humiliate, sink, degrade advance, elevate, honor, raise, aggrandize, exalt, promote, uplift, dignify
abash bewilder, daunt, embarrass, mortify, chagrin, discompose, humble, overawe, confound, disconcert, humiliate, shame, confuse, dishearten animate, cheer, encourage, rally, buoy, embolden, inspirit, uphold
abate decline, ebb, mitigate, reduce, decrease, lessen, moderate, subside, diminish, lower aggravate, enhance, foment, rage, amplify, enlarge, increase, raise, continue, extend, magnify, revive, develop
abbreviation abridgment, contraction
abet advocate, countenance, incite, sanction, aid, embolden, instigate, support, assist, encourage, promote, uphold baffle, deter, dissuade, hinder, confound, disapprove, expose, impede, counteract, disconcert, frustrate, obstruct, denounce, discourage
abhor abominate, dislike, loathe, scorn, despise, hate, nauseate, shun, detest admire, crave, esteem, love, approve, desire, like, relish, covet, enjoy
abide anticipate, dwell, remain, stop, await, endure, reside, tarry, bear, expect, rest, tolerate, bide, inhabit, sojourn, wait, confront, live, stay, watch, continue, lodge abandon, forfeit, migrate, reject, avoid, forfend, move, resist, depart, journey, proceed, shun
abolish abate, eradicate, prohibit, stamp out, abrogate, exterminate, remove, subvert, annihilate, extirpate, repeal, supplant, annul, nullify, reverse, suppress, destroy, obliterate, revoke, terminate, end, overthrow, set aside authorize, establish, reinstate, revive, cherish, institute, renew, set up, confirm, introduce, repair, support, continue, legalize, restore, sustain, enact, promote
abomination abhorrence, curse, hatred, plague, abuse, detestation, horror, shame, annoyance, disgust, iniquity, villainy, aversion, evil, nuisance, wickedness, crime, execration, offense affection, blessing, enjoyment, joy, appreciation, delight, esteem, satisfaction, approval, desire, gratification, treat, benefit
abridgment abbreviation, compend, epitome, summary, abstract, compendium, outline, synopsis, analysis, digest
absolute arbitrary, compulsory, haughty, peremptory, arrogant, controlling, imperative, positive, authoritative, despotic, imperious, supreme, autocratic, dictatorial, irresponsible, tyrannical, coercive, dogmatic, lordly, unconditional, commanding, domineering, overbearing, unequivocal, compulsive, exacting accountable, constitutional, gentle, lowly, responsible, complaisant, contingent, humble, meek, submissive, compliant, docile, lenient, mild, yielding, conditional, ductile, limited
absolve acquit, exculpate, forgive, pardon, clear, exempt, free, release, discharge, exonerate, liberate, set free accuse, charge, condemn, impeach, obligate, bind, compel, convict, inculpate, oblige
absorb consume, engross, suck up, take in, drink in, exhaust, swallow, take up, drink up, imbibe, swallow up cast out, dissipate, emit, put forth, shoot forth, disgorge, distract, exude, radiate, throw off, disperse, eject, give up, send out, vomit
abstinence abstemiousness, frugality, self-denial, sobriety, continence, moderation, self-restraint, temperance, fasting, self-control drunkenness, greed, reveling, sensuality, excess, intemperance, revelry, wantonness, gluttony, intoxication, self-indulgence
abstract appropriate, distract, purloin, steal, detach, divert, remove, take away, discriminate, eliminate, separate, withdraw, distinguish add, complete, fill up, restore, unite, combine, conjoin, increase, strengthen
abstracted absent, heedless, listless, preoccupied, absent-minded, inattentive, negligent, thoughtless, absorbed, indifferent, oblivious alert, on hand, ready, wide-awake, attentive, prompt, thoughtful
absurd anomalous, ill-considered, ludicrous, ridiculous, chimerical, ill-judged, mistaken, senseless, erroneous, inconclusive, monstrous, stupid, false, incorrect, nonsensical, unreasonable, foolish, infatuated, paradoxical, wild, ill-advised, irrational, preposterous certain, incontrovertible, rational, substantial, consistent, indisputable, reasonable, true, demonstrable, indubitable, sagacious, undeniable, demonstrated, infallible, sensible, unquestionable, established, logical, sound, wise, incontestable
abuse aggrieve, impose on or, oppress, ruin, damage, upon, persecute, slander, defame, injure, pervert, victimize, defile, malign, prostitute, vilify, disparage, maltreat, rail at, violate, harm, misemploy, ravish, vituperate, ill-treat, misuse, reproach, wrong, ill-use, molest, revile applaud, conserve, favor, protect, sustain, benefit, consider, laud, regard, tend, care for, eulogize, panegyrize, respect, uphold, cherish, extol, praise, shield, vindicate
accessory abetter or abettor, associate, companion, henchman, accomplice, attendant, confederate, participator, ally, coadjutor, follower, partner, assistant, colleague, helper, retainer adversary, chief, foe, leader, principal, antagonist, commander, hinderer, opponent, rival, betrayer, enemy, instigator, opposer
accident adventure, contingency, happening, misfortune, calamity, disaster, hazard, mishap, casualty, fortuity, incident, possibility, chance, hap, misadventure appointment, decree, intention, ordainment, preparation, calculation, fate, law, ordinance, provision, certainty, foreordination, necessity, plan, purpose
acquaintance association, experience, fellowship, intimacy, companionship, familiarity, friendship, knowledge ignorance, ignoring, inexperience, unfamiliarity
acrimony acerbity, harshness, severity, tartness, asperity, malignity, sharpness, unkindness, bitterness, moroseness, sourness, virulence, causticity amiability, gentleness, kindness, smoothness, courtesy, good nature, mildness, sweetness
act accomplishment, execution, movement, achievement, exercise, operation, action, exertion, performance, consummation, exploit, proceeding, deed, feat, transaction, doing, motion, work, effect cessation, immobility, inertia, quiet, suffering, deliberation, inaction, passion[A], repose, suspension, endurance, inactivity, quiescence, rest
active agile, energetic, officious, sprightly, alert, expeditious, prompt, spry, brisk, industrious, quick, supple, bustling, lively, ready, vigorous, busy, mobile, restless, wide awake, diligent, nimble dull, inactive, lazy, slow, heavy, indolent, quiescent, sluggish, idle, inert, quiet, stupid
acumen acuteness, insight, perspicacity, sharpness, cleverness, keenness, sagacity, shrewdness, discernment, penetration bluntness, dulness, obtuseness, stupidity
add adjoin, annex, augment, extend, make up, affix, append, cast up, increase, subjoin, amplify, attach, enlarge, join on, sum up abstract, diminish, lessen, remove, withdraw, deduct, dissever, reduce, subtract
addicted abandoned, devoted, given over, inclined, accustomed, disposed, given up, prone, attached, given, habituated, wedded averse, disinclined, indisposed, unaccustomed
address cost, approach, hail, speak to, apostrophize, court, salute, woo, appeal, greet avoid, elude, overlook, pass by, cut, ignore, pass, shun
address adroitness, discretion, manners, readiness, courtesy, ingenuity, politeness, tact, dexterity awkwardness, clumsiness, ill-breeding, stupidity, boorishness, fatuity, ill manners, unmannerliness, clownishness, folly, rudeness, unwisdom
adequate able, competent, fitted, satisfactory, adapted, equal, fitting, sufficient, capable, fit, qualified, suitable, commensurate disqualified, inferior, unequal, unsatisfactory, useless, inadequate, insufficient, unfit, unsuitable, worthless, incompetent, poor, unqualified
adherent aid, ally, disciple, partisan, supporter, aider, backer, follower adversary, betrayer, enemy, opponent, traitor, antagonist, deserter, hater, renegade
adhesive cohesive, gummy, sticky, viscous, glutinous, sticking, viscid free, inadhesive, loose, separable
adjacent abutting, bordering, contiguous, neighboring, adjoining, close, coterminous, next, attached, conterminous, near, nigh, beside detached, disconnected, disjoined, distant, remote, separate
admire adore, delight in, extol, respect, venerate, applaud, enjoy, honor, revere, wonder, approve, esteem, love abhor, contemn, detest, execrate, ridicule, abominate, despise, dislike, hate, scorn
adorn beautify, decorate, garnish, illustrate, bedeck, embellish, gild, ornament, deck deface, deform, disfigure, mar, spoil
affront aggravate, exasperate, offend, vex, annoy, insult, provoke, wound, displease, irritate, tease conciliate, content, gratify, honor, please
agent actor, factor, means, operator, promoter, doer, instrument, mover, performer chief, inventor, originator, principal
agree accede, admit, coincide, concur, accept, approve, combine, consent, accord, assent, comply, harmonize, acquiesce contend, demur, disagree, oppose, contradict, deny, dispute, protest, decline, differ, dissent, refuse
agriculture cultivation, gardening, kitchen-gardening, culture, horticulture, market-gardening, farming, husbandry, tillage, floriculture
aim aspiration, endeavor, intention, tendency, design, goal, mark, determination, inclination, object, end, intent, purpose aimlessness, heedlessness, negligence, purposelessness, avoidance, neglect, oversight, thoughtlessness, carelessness
air appearance, demeanor, manner, sort, bearing, expression, mien, style, behavior, fashion, port, way, carriage, look
airy aerial, ethereal, frolicsome, joyous, lively, animated, fairylike, gay, light, sprightly clumsy, heavy, ponderous, sluggish, wooden, dull, inert, slow, stony
alarm affright, disquietude, fright, solicitude, apprehension, dread, misgiving, terror, consternation, fear, panic, timidity, dismay assurance, calmness, confidence, repose, security
alert active, lively, prepared, vigilant, brisk, nimble, prompt, watchful, hustling, on the watch, ready, wide-awake drowsy, dull, heavy, inactive, slow, sluggish, stupid
alien conflicting, distant, inappropriate, strange, contradictory, foreign, irrelevant, unconnected, contrary, hostile, opposed, unlike, contrasted, impertinent, remote akin, apropos, germane, proper, appropriate, essential, pertinent, relevant
alien foreigner, stranger citizen, fellow-countryman, native-born inhabitant, countryman, native, naturalized person
alike akin, equivalent, kindred, same, analogous, homogeneous, like, similar, equal, identical, resembling, uniform different, dissimilar, distinct, heterogeneous, unlike
alive active, breathing, live, quick, alert, brisk, lively, subsisting, animate, existent, living, vivacious, animated, existing dead, defunct, dull, lifeless, deceased, dispirited, inanimate, spiritless
allay alleviate, compose, quiet, still, appease, mollify, soothe, tranquilize, calm, pacify agitate, excite, kindle, rouse, stir up, arouse, fan, provoke, stir
allege adduce, asseverate, claim, maintain, produce, advance, assign, declare, offer, say, affirm, aver, introduce, plead, state, assert, cite
allegiance devotion, fealty, loyalty, obedience, subjection, faithfulness, homage disaffection, disloyalty, rebellion, sedition, treason
allegory fable, fiction, illustration, metaphor, parable, simile chronicle, fact, history, narrative, record
alleviate abate, lighten, reduce, remove, assuage, mitigate, relieve, soften, lessen, moderate aggravate, embitter, heighten, intensify, make worse, augment, enhance, increase, magnify
alliance coalition, confederation, fusion, partnership, compact, federation, league, union, confederacy antagonism, disunion, enmity, schism, separation, discord, divorce, hostility, secession, war
allot appoint, destine, give, portion out, apportion, distribute, grant, select, assign, divide, mete out, set apart, award appropriate, deny, resume, seize, confiscate, refuse, retain, withhold
allow admit, consent to, let, sanction, tolerate, concede, grant, permit, suffer, yield deny, disapprove, protest, reject, withstand, disallow, forbid, refuse, resist
alloy admixture, adulteration, debasement, deterioration
allude advert, indicate, intimate, point, signify, hint, insinuate, mention, refer, suggest, imply
allure attract, captivate, decoy, entice, lure, tempt, cajole, coax, draw, inveigle, seduce, win chill, damp, deter, dissuade, drive away, repel, warn
also as well, in addition, likewise, too, as well as, in like manner, similarly, withal, besides but, nevertheless, on the contrary, yet, in spite of, notwithstanding, on the other hand
alternative choice, election, option, pick, preference, resource compulsion, necessity
amass accumulate, collect, heap up, hoard up, store up, aggregate, gather, hoard, pile up disperse, divide, portion, spend, waste, dissipate, parcel, scatter, squander
amateur connoisseur, critic, dilettante, novice, tyro
amazement admiration, awe, confusion, surprise, astonishment, bewilderment, perplexity, wonder anticipation, composure, expectation, preparation, steadiness, calmness, coolness, indifference, self-possession, stoicism
ambition aspiration, competition, emulation, opposition, rivalry carelessness, contentment, humility, indifference, satisfaction
amend advance, correct, meliorate, rectify, ameliorate, emend, mend, reform, better, improve, mitigate, repair, cleanse, make better, purify aggravate, debase, harm, mar, tarnish, blemish, depress, impair, spoil, vitiate, corrupt, deteriorate, injure
amiable agreeable, engaging, lovable, pleasing, attractive, gentle, lovely, sweet, benignant, good-natured, loving, winning, harming, kind, pleasant, winsome acrimonious, crusty, hateful, ill-tempered, surly, churlish, disagreeable, ill-conditioned, morose, unamiable, crabbed, dogged, ill-humored, sour, unlovely, cruel, gruff, ill-natured, sullen
amid amidst, amongst, betwixt, mingled with, among, between, in the midst of, surrounded by afar from, away from, beyond, far from, outside, without
amplify augment, dilate, expand, extend, unfold, develop, enlarge, expatiate, increase, widen abbreviate, amputate, condense, cut down, reduce, summarize, abridge, "boil down", curtail, epitomize, retrench, sum up
analogy affinity, likeness, relation, similarity, coincidence, parity, resemblance, simile, comparison, proportion, semblance, similitude disagreement, disproportion, dissimilarity, incongruity, unlikeness
anger animosity, fury, offense, rage, choler, impatience, passion, resentment, displeasure, indignation, peevishness, temper, exasperation, ire, pettishness, vexation, fretfulness, irritation, petulance, wrath amiability, gentleness, long-suffering, patience, peacefulness, charity, leniency, love, peace, self-control, forbearance, lenity, mildness, peaceableness, self-restraint
animal beast, fauna, living organism, sentient being, brute, living creature angel, man, mind, soul, substance (material), inanimate object, matter, mineral, spirit, vegetable
announce advertise, give notice (of), proclaim, reveal, circulate, give out, promulgate, say, communicate, herald, propound, spread abroad, declare, make known, publish, state, enunciate, notify, report, tell bury, cover (up), hush, keep secret, suppress, conceal, hide, keep back, secrete, withhold
answer rejoinder, repartee, reply, response, retort
anticipate apprehend, forecast, hope, expect, foretaste, look forward to despair of, distrust, doubt, dread, fear, recall, recollect, remember
anticipation antepast, expectation, foresight, hope, apprehension, foreboding, foretaste, presentiment, expectancy, forecast, forethought, prevision astonishment, despair, dread, fear, surprise, consummation, doubt, enjoyment, realization, wonder
antipathy abhorrence, disgust, hatred, repugnance, antagonism, dislike, hostility, repulsion, aversion, distaste, opposition, uncongeniality, detestation affinity, attraction, fellow-feeling, kindliness, sympathy, agreement, congeniality, harmony, regard
antique ancient, old-fashioned, quaint, superannuated, antiquated fashionable, fresh, modern, modish, new, recent, stylish
anxiety anguish, disquiet, foreboding, perplexity, apprehension, disturbance, fretfulness, solicitude, care, dread, fretting, trouble, concern, fear, misgiving, worry apathy, calmness, confidence, light-heartedness, satisfaction, assurance, carelessness, ease, nonchalance, tranquillity
apathy calmness, indifference, quietness, stoicism, composure, insensibility, quietude, tranquillity, immobility, lethargy, sluggishness, unconcern, impassibility, phlegm, stillness, unfeelingness agitation, disturbance, feeling, sensibility, sympathy, alarm, eagerness, frenzy, sensitiveness, turbulence, anxiety, emotion, fury, storm, vehemence, care, excitement, passion, susceptibility, violence, distress
apiece distributively, each, individually, separately, severally accumulatively, confusedly, indiscriminately, together, unitedly, collectively, en masse, synthetically
apology acknowledgment, defense, excuse, plea, confession, exculpation, justification, vindication accusation, charge, condemnation, injury, offense, censure, complaint, imputation, insult, wrong
apparent likely, presumable, probable, seeming doubtful, dubious, improbable, unimaginable, unlikely
appear have the appearance or semblance, look, seem be, be certain real or true, be the fact, exist
appendage accessory, addition, appurtenance, concomitant, accompaniment, adjunct, attachment, extension, addendum, appendix, auxiliary, supplement main body, original, total, whole
appetite appetency, impulse, lust, propensity, craving, inclination, passion, relish, desire, liking, proclivity, thirst, disposition, longing, proneness, zest antipathy, detestation, dislike, distaste, indifference, repugnance, aversion, disgust, disrelish, hatred, loathing, repulsion
apportion allot, appropriate, deal, distribute, grant, appoint, assign, dispense, divide, share cling to, consolidate, gather together, receive, collect, divide arbitrarily, keep together, retain
approximation approach, likeness, neighborhood, resemblance, contiguity, nearness, propinquity, similarity difference, distance, error, remoteness, unlikeness, variation
arms accouterments, armor, harness, mail, weapons
army armament, forces, military, soldiers, array, host, multitude, soldiery, force, legions, phalanx, troops
arraign accuse, charge, impeach, prosecute, censure, cite, indict, summon acquit, discharge, exonerate, overlook, release, condone, excuse, forgive, pardon, set free
array army, collection, line of battle, parade, arrangement, disposition, order, show, battle array, exhibition, order of battle, sight
arrest apprehend, detain, restrain, stop, capture, hold, secure, take into custody, catch, make prisoner, seize, take prisoner discharge, dismiss, free, liberate, release, set free
artifice art, craft, finesse, invention, stratagem, blind, cunning, fraud, machination, subterfuge, cheat, device, guile, maneuver, trick, contrivance, dodge, imposture, ruse, wile artlessness, fairness, guilelessness, ingenuousness, openness, sincerity, candor, frankness, honesty, innocence, simplicity, truth
artist artificer, artisan, mechanic, operative, workman
ask beg, crave, entreat, petition, request, solicit, beseech, demand, implore, pray, require, supplicate claim, command, deny, enforce, exact, extort, insist, refuse, reject
associate accomplice, coadjutor, comrade, fellow, mate, ally, colleague, confederate, friend, partner, chum, companion, consort, helpmate, peer antagonist, enemy, foe, hinderer, opponent, opposer, rival, stranger
association alliance, confederacy, familiarity, lodge, club, confederation, federation, participation, community, conjunction, fellowship, partnership, companionship, connection, fraternity, society, company, corporation, friendship, union disintegration, independence, isolation, separation, solitude
assume accept, arrogate, postulate, put on, affect, claim, presume, take, appropriate, feign, pretend, usurp
assurance arrogance, boldness, impudence, self-confidence, assertion, confidence, presumption, self-reliance, assumption, effrontery, self-assertion, trust bashfulness, consternation, distrust, hesitancy, shyness, confusion, dismay, doubt, misgiving, timidity
astute acute, discerning, penetrating, sharp, clear-sighted, discriminating, penetrative, shrewd, crafty, keen, perspicacious, subtile, cunning, knowing, sagacious, subtle blind, idiotic, shallow, stolid, undiscerning, dull, imbecile, short-sighted, stupid, unintelligent
attachment adherence, devotion, friendship, regard, adhesion, esteem, inclination, tenderness, affection, estimation, love, union alienation, aversion, distance, estrangement, repugnance, animosity, coolness, divorce, indifference, separation, antipathy, dislike, enmity, opposition, severance
attack assail, beset, combat, invade, assault, besiege, encounter, set upon, beleaguer, charge, fall upon, storm aid, cover, protect, shelter, support, uphold, befriend, defend, resist, shield, sustain, withstand
attack aggression, incursion, invasion, onslaught, assault, infringement, onset, trespass, encroachment, intrusion defense, repulsion, resistance, retreat, submission, surrender
attain accomplish, arrive at, gain, master, reach, achieve, compass, get, obtain, secure, acquire, earn, grasp, procure, win abandon, fail, forfeit, give up, let go, lose, miss
attitude pose, position, posture
attribute ascribe, associate, connect, impute, refer, assign, charge deny, disconnect, dissociate, separate, sever, sunder
attribute property, quality being, essence, nature, substance
augur betoken, divine, foretell, predict, prognosticate, bode, forebode, portend, presage, prophesy assure, demonstrate, establish, make sure, settle, calculate, determine, insure, prove, warrant
authentic accepted, certain, original, sure, accredited, current, real, true, authoritative, genuine, received, trustworthy, authorized, legitimate, reliable, veritable apocryphal, counterfeit, exploded, false, spurious, baseless, disputed, fabulous, fictitious, unauthorized
auxiliary accessory, ally, coadjutor, helper, promoter, aid, assistant, confederate, mercenary, subordinate antagonist, hinderer, opponent, opposer
avaricious close, greedy, niggardly, penurious, sordid, covetous, miserly, parsimonious, rapacious, stingy bountiful, free, generous, liberal, munificent, prodigal, wasteful
avenge punish, retaliate, revenge, vindicate, visit
avow knowledge, aver, confess, own, profess, testify, admit, avouch, declare, proclaim, protest, witness contradict, deny, disavow, disclaim, disown, ignore, repudiate
awful alarming, direful, frightful, majestic, solemn, appalling, dread, grand, noble, stately, august, dreadful, horrible, portentous, terrible, dire, fearful, imposing, shocking, terrific base, contemptible, inferior, paltry, beggarly, despicable, lowly, undignified, commonplace, humble, mean, vulgar
awkward boorish, clumsy, rough, unhandy, bungling, gawky, uncouth, unskilful, clownish, maladroit, ungainly adroit, clever, dexterous, handy, skilful
axiom absurdity, contradiction, demonstration, nonsense, paradox, sophism
babble blab, cackle, gabble, murmur, prattle, blurt, chat, gossip, palaver, tattle, blurt out, chatter, jabber, prate, twaddle
banish ban, dismiss, evict, expatriate, ostracize, discharge, drive out, exile, expel, oust, dislodge, eject
bank beach, bound, brink, edge, margin, shore, border, brim, coast, marge, rim, strand
banter badinage, derision, jeering, raillery, sarcasm, chaff, irony, mockery, ridicule, satire
barbarous atrocious, brutal, merciless, uncivilized, barbarian, cruel, rude, uncouth, barbaric, inhuman, savage, untamed civilized, cultured, elegant, humane, polite, tender, courtly, delicate, graceful, nice, refined, urbane
barrier bar, bulwark, obstruction, rampart, barricade, hindrance, parapet, restraint, breastwork, obstacle, prohibition, restriction admittance, opening, road, transit, entrance, passage, thoroughfare, way
battle action, combat, encounter, passage of arms, affair, conflict, engagement, skirmish, bout, contest, fight, strife armistice, concord, peace, suspension of hostilities, truce
beat bastinado, chastise, overcome, spank, thrash, batter, conquer, pommel, strike, vanquish, belabor, cudgel, pound, surpass, whip, bruise, defeat, scourge, switch, worst, castigate, flog, smite fail, fall, get the worst of, go down, go under, surrender
beautiful attractive, charming, exquisite, handsome, beauteous, comely, fair, lovely, bewitching, delightful, fine, picturesque, bonny, elegant, graceful, pretty awkward, frightful, grotesque, repulsive, uncouth, clumsy, ghastly, hideous, shocking, ungainly, deformed, grim, horrid, ugly, unlovely, disgusting, grisly, odious, unattractive, unpleasant
because as, for, inasmuch as, since altho, however, nevertheless, notwithstanding, yet
becoming befitting, congruous, fit, meet, seemly, beseeming, decent, fitting, neat, suitable, comely, decorous, graceful, proper, worthy awkward, ill-fitting, indecent, unbecoming, unseemly, ill-becoming, improper, indecorous, unfit, unsuitable
beginning arising, inauguration, origin, source, commencement, inception, outset, spring, fount, initiation, rise, start, fountain, opening
behavior action, breeding, conduct, deportment, manner, bearing, carriage, demeanor, life, manners
bend bias, curve, diverge, mold, submit, twist, bow, deflect, incline, persuade, turn, warp, crook, deviate, influence, stoop, twine, yield
benevolence almsgiving, charity, kind-heartedness, munificence, beneficence, generosity, kindliness, philanthropy, benignity, good-will, kindness, sympathy, bounty, humanity, liberality, unselfishness barbarity, greediness, ill-will, malignity, self-seeking, brutality, harshness, inhumanity, niggardliness, stinginess, churlishness, illiberality, malevolence, selfishness, unkindness
bind compel, fetter, oblige, restrict, shackle, engage, fix, restrain, secure, tie, fasten free, loose, set free, unbind, unfasten, unloose, untie
bitter acerb, acidulous, caustic, pungent, stinging, acetous, acrid, cutting, savage, tart, acid, acrimonious, harsh, sharp, vinegarish, acidulated, biting, irate, sour, virulent dulcet, honeyed, luscious, nectared, saccharine, sweet
bleach blanch, make white, whiten, whitewash blacken, color, darken, dye, soil, stain
blemish blot, defacement, disgrace, injury, spot, blur, defect, dishonor, reproach, stain, brand, deformity, fault, smirch, stigma, crack, dent, flaw, soil, taint, daub, disfigurement, imperfection, speck, tarnish
blow box, concussion, disaster, misfortune, stripe, buffet, cuff, knock, rap, stroke, calamity, cut, lash, shock, thump
bluff abrupt, brusk, impolite, rough, blunt, coarse, inconsiderate, rude, blustering, discourteous, open, uncivil, bold, frank, plain-spoken, unmannerly bland, courteous, genial, polished, polite, refined, reserved, urbane
body ashes, clay, dust, frame, system, carcass, corpse, form, remains, trunk intellect, intelligence, mind, soul, spirit
both twain, two each, either, every, neither, none, no one, not any
boundary barrier, confines, limit, margin, border, edge, line, term, bound, enclosure, marches, termination, bourn, frontier, marge, verge, bourne, landmark center, citadel, estate, inside, interior, land, region, territory
brave adventurous, courageous, fearless, undaunted, bold, daring, gallant, undismayed, chivalric, dauntless, heroic, valiant, chivalrous, doughty, intrepid, venturesome afraid, cringing, fearful, pusillanimous, timid, cowardly, faint-hearted, frightened, shrinking, timorous
break bankrupt, crack, destroy, rive, shatter, split, burst, crush, fracture, rupture, shiver, sunder, cashier, demolish, rend, sever, smash, transgress attach, bind, fasten, join, mend, secure, solder, unite, weld
brutish animal, brutal, ignorant, sensual, swinish, base, brute, imbruted, sottish, unintellectual, beastly, carnal, insensible, stolid, unspiritual, bestial, coarse, lascivious, stupid, vile elevated, exalted, great, intellectual, noble, enlightened, grand, humane, intelligent, refined
burn blaze, char, flame, incinerate, set fire to, brand, consume, flash, kindle, set on fire, cauterize, cremate, ignite, scorch, singe cool, extinguish, put out, smother, stifle, subdue
business affair, commerce, handicraft, trading, art, concern, job, traffic, avocation, craft, occupation, transaction, barter, duty, profession, vocation, calling, employment, trade, work
but and, however, notwithstanding, that, barely, just, only, tho, besides, merely, provided, unless, except, moreover, save, yet, further, nevertheless, still
by by dint of, by means of, through, with
cabal combination, confederacy, crew, gang, conclave, conspiracy, faction, junto
calculate account, consider, enumerate, rate, cast, count, estimate, reckon, compute, deem, number, sum up
call bawl, cry (out), roar, shriek, bellow, ejaculate, scream, vociferate, clamor, exclaim, shout, yell be silent, be still, hark, hearken, hush, list, listen
calm collected, imperturbable, sedate, still, composed, peaceful, self-possessed, tranquil, cool, placid, serene, undisturbed, dispassionate, quiet, smooth, unruffled agitated, excited, frenzied, passionate, ruffled, violent, boisterous, fierce, furious, raging, stormy, wild, disturbed, frantic, heated, roused, turbulent, wrathful
cancel abolish, discharge, nullify, rescind, abrogate, efface, obliterate, revoke, annul, erase, quash, rub off or out, blot out, expunge, remove, scratch out, cross off or out, make void, repeal, vacate approve, enact, establish, perpetuate, reenact, uphold, confirm, enforce, maintain, record, sustain, write
candid aboveboard, honest, open, truthful, artless, impartial, simple, unbiased, fair, ingenuous, sincere, unprejudiced, frank, innocent, straightforward, unreserved, guileless, naive, transparent, unsophisticated adroit, cunning, diplomatic, intriguing, sharp, subtle, artful, deceitful, foxy, knowing, shrewd, tricky, crafty, designing, insincere, maneuvering, sly, wily
caparison accouterments, harness, housings, trappings
capital chief city, metropolis, seat of government
care anxiety, concern, oversight, trouble, attention, direction, perplexity, vigilance, caution, forethought, precaution, wariness, charge, heed, prudence, watchfulness, circumspection, management, solicitude, worry carelessness, heedlessness, indifference, negligence, oversight, remissness, disregard, inattention, neglect, omission, recklessness, slight
career charge, flight, passage, race, course, line of achievement, public life, rush
caress coddle, embrace, fondle, pamper, court, flatter, kiss, pet
caricature burlesque, extravaganza, mimicry, take-off, exaggeration, imitation, parody, travesty
carry bear, convey, move, sustain, transmit, bring, lift, remove, take, transport drop, fall under, give up, let go, shake off, throw down, throw off
catastrophe calamity, denouement, mischance, mishap, cataclysm, disaster, misfortune, sequel benefit, boon, favor, pleasure, prosperity, blessing, comfort, help, privilege, success
catch apprehend, comprehend, grasp, overtake, snatch, capture, discover, grip, secure, take, clasp, ensnare, gripe, seize, take hold of, clutch, entrap, lay hold of (on upon) fail of, give up, lose, release, throw aside, fall short of, let go, miss, restore, throw away
cause actor, causality, designer, occasion, precedent, agent, causation, former, origin, reason, antecedent, condition, fountain, originator, source, author, creator, motive, power, spring consequence, development, end, fruit, outcome, product, creation, effect, event, issue, outgrowth, result
cease abstain, desist, give over, quit, bring to an end, discontinue, intermit, refrain, come to an end, end, leave off, stop, conclude, finish, pause, terminate begin, enter upon, initiate, originate, set going, set on foot, commence, inaugurate, institute, set about, set in operation, start
celebrate commemorate, keep, observe, solemnize contemn, dishonor, forget, neglect, profane, despise, disregard, ignore, overlook, violate
center middle, midst bound, boundary, circumference, perimeter, rim
chagrin confusion, discomposure, humiliation, shame, disappointment, dismay, mortification, vexation delight, exultation, glory, rejoicing, triumph
change alter, exchange, shift, transmute, commute, metamorphose, substitute, turn, convert, modify, transfigure, vary, diversify, qualify, transform, veer abide, continue, hold, persist, retain, bide, endure, keep, remain, stay
change alteration, mutation, renewing, transmutation, conversion, novelty, revolution, variation, diversity, regeneration, transformation, variety, innovation, renewal, transition, vicissitude constancy, fixedness, invariability, steadiness, continuance, fixity, permanence, unchangeableness, firmness, identity, persistence, uniformity
character constitution, genius, personality, reputation, temper, disposition, nature, record, spirit, temperament
characteristic attribute, feature, peculiarity, sign, trace, character, indication, property, singularity, trait, distinction, mark, quality
charming bewitching, delightful, enrapturing, fascinating, captivating, enchanting, entrancing, winning
chasten afflict, chastise, discipline, punish, refine, subdue, castigate, correct, humble, purify, soften, try
cherish cheer, encourage, harbor, nurse, shelter, cling to, entertain, hold dear, nurture, treasure, comfort, foster, nourish, protect, value
choose cull, elect, pick, pick out, prefer, select cast away, decline, dismiss, refuse, repudiate, cast out, disclaim, leave, reject, throw aside
circumlocution diffuseness, prolixity, surplusage, verbiage, periphrasis, redundance, tautology, verbosity, pleonasm, redundancy, tediousness, wordiness brevity, compression, condensation, plainness, succinctness, compactness, conciseness, directness, shortness, terseness
circumstance accompaniment, fact, item, point, concomitant, feature, occurrence, position, detail, incident, particular, situation, event
class association, circle, clique, company, grade, rank, caste, clan, club, coterie, order, set
cleanse brush, dust, purify, scour, sponge, wash, clean, lave, rinse, scrub, sweep, wipe, disinfect, mop befoul, besmirch, contaminate, debase, deprave, soil, stain, taint, besmear, bespatter, corrupt, defile, pollute, spoil, sully, vitiate
clear apparent, intelligible, pellucid, transparent, diaphanous, limpid, perspicuous, unadorned, distinct, lucid, plain, unambiguous, evident, manifest, straightforward, unequivocal, explicit, obvious, translucent, unmistakable ambiguous, dim, foggy, mysterious, opaque, unintelligible, cloudy, dubious, indistinct, obscure, turbid, vague
clever able, capable, happy, keen, sharp, adroit, dexterous, ingenious, knowing, skilful, apt, expert, intellectual, quick, smart, bright, gifted, intelligent, quick-witted, talented awkward, clumsy, foolish, ignorant, slow, thick-headed, bungling, dull, idiotic, senseless, stupid, witless
collision clash, concussion, contact, impact, opposition, clashing, conflict, encounter, meeting, shock agreement, coincidence, concord, conformity, unison, amity, concert, concurrence, harmony, unity
comfortable agreeable, cheery, genial, snug, at ease, commodious, pleasant, well-off, at rest, contented, satisfactory, well-provided, cheerful, convenient, satisfied, well-to-do cheerless, discontented, distressed, forlorn, uncomfortable, disagreeable, dissatisfied, dreary, miserable, wretched
commit assign, confide, consign, entrust, relegate, trust
company assemblage, concourse, convocation, host, assembly, conference, crowd, meeting, collection, congregation, gathering, multitude, conclave, convention, group, throng dispersion, loneliness, privacy, retirement, seclusion, solitude
compel coerce, drive, make, oblige, constrain, force, necessitate
complain croak, growl, grunt, remonstrate, find fault, grumble, murmur, repine applaud, approve, commend, eulogize, laud, praise
complex abstruse, confused, intricate, mixed, complicated, conglomerate, involved, multiform, composite, entangled, manifold, obscure, compound, heterogeneous, mingled, tangled clear, homogeneous, plain, uncombined, uniform, direct, obvious, simple, uncompounded, unraveled
condemn blame, convict, doom, reprove, censure, denounce, reprobate, sentence absolve, applaud, exonerate, pardon, acquit, approve, justify, praise
confess accept, allow, concede, grant, acknowledge, avow, disclose, own, admit, certify, endorse, recognize cloak, deny, disown, hide, screen, conceal, disavow, dissemble, mask, secrete, cover, disguise, dissimulate, repudiate, veil
confirm assure, fix, sanction, substantiate, corroborate, prove, settle, sustain, establish, ratify, strengthen, uphold abrogate, cancel, overthrow, shatter, upset, annul, destroy, shake, unsettle, weaken
congratulate condole with, console
conquer beat, humble, overthrow, subject, checkmate, master, prevail over, subjugate, crush, overcome, put down, surmount, defeat, overmaster, reduce, vanquish, discomfit, overmatch, rout, win, down, overpower, subdue, worst capitulate, fail, fly, lose, retire, submit, surrender, cede, fall, forfeit, resign, retreat, succumb, yield
conscious advised, assured, certain, cognizant, sensible, apprised, aware, certified, informed, sure cold, dead, deaf, ignorant, insensible, unaware, unconscious
consequence consequent, end, issue, outgrowth, sequel, effect, event, outcome, result, upshot
console comfort, condole with, encourage, sympathize with annoy, distress, disturb, grieve, hurt, sadden, trouble, wound
continual ceaseless, incessant, regular, uninterrupted, constant, invariable, unbroken, unremitting, continuous, perpetual, unceasing, unvarying
contract agreement, cartel, engagement, pledge, arrangement, compact, obligation, promise, bargain, covenant, pact, stipulation
contrast compare, differentiate, discriminate, oppose
conversation chat, communion, converse, intercourse, colloquy, confabulation, dialogue, parley, communication, conference, discourse, talk
convert disciple, neophyte, proselyte
convey carry, give, remove, shift, transmit, change, move, sell, transfer, transport cling to, hold, keep, possess, preserve, retain
convoke assemble, call together, convene, muster, call, collect, gather, summon adjourn, disband, dismiss, dissolve, scatter, break up, discharge, disperse, prorogue, separate
criminal abominable, flagitious, immoral, sinful, vile, culpable, guilty, iniquitous, unlawful, wicked, felonious, illegal, nefarious, vicious, wrong innocent, lawful, meritorious, right, just, legal, moral, virtuous
daily nightly, nocturnal
danger hazard, insecurity, jeopardy, peril, risk defense, immunity, protection, safeguard, safety, security, shelter
dark black, dusky, mysterious, sable, somber, dim, gloomy, obscure, shadowy, swart, dismal, murky, opaque, shady, swarthy bright, crystalline, glowing, lucid, shining, brilliant, dazzling, illumined, luminous, transparent, clear, gleaming, light, radiant, white
decay corrupt, decompose, molder, putrefy, rot, spoil
deception craft, dissimulation, finesse, lie, cunning, double-dealing, fraud, lying, deceit, duplicity, guile, prevarication, deceitfulness, fabrication, hypocrisy, trickery, delusion, falsehood, imposition, untruth candor, frankness, honesty, simplicity, truth, fair dealing, guilelessness, openness, sincerity, veracity
defense apology, guard, rampart, shelter, bulwark, justification, resistance, shield, fortress, protection, safeguard, vindication abandonment, betrayal, capitulation, desertion, flight, surrender
defile befoul, corrupt, pollute, spoil, sully, tarnish, contaminate, infect, soil, stain, taint, vitiate clean, cleanse, disinfect, hallow, purify, sanctify, wash
definition comment, description, exposition, rendering, commentary, explanation, interpretation, translation
delegate deputy, legate, proxy, representative, substitute
deliberate confer, consult, meditate, reflect, consider, debate, ponder, weigh
delicious dainty, delightful, exquisite, luscious, savory acrid, bitter, loathsome, nauseous, repulsive, unpalatable, unsavory
delightful acceptable, delicious, pleasant, refreshing, agreeable, grateful, pleasing, satisfying, congenial, gratifying, pleasurable, welcome depressing, distressing, horrible, miserable, painful, woful, disappointing, hateful, melancholy, mournful, saddening, wretched
delusion error, fallacy, hallucination, illusion, phantasm actuality, certainty, fact, reality, truth, verity
demolish destroy, overthrow, overturn, raze, ruin build, construct, create, make, repair, restore
demonstration certainty, consequence, evidence, inference, conclusion, deduction, induction, proof
design aim, final cause, object, proposal, device, intent, plan, purpose, end, intention, project, scheme
desire appetency, concupiscence, hankering, proclivity, appetite, coveting, inclination, propensity, aspiration, craving, longing, wish
despair desperation, despondency, discouragement, hopelessness anticipation, cheer, courage, encouragement, expectation, hopefulness, assurance, confidence, elation, expectancy, hope, trust
dexterity adroitness, aptitude, cleverness, expertness, readiness, skill
diction expression, phrase, style, vocabulary, language, phraseology, verbiage, wording
die cease, decline, expire, perish, decease, depart, fade, wither be born, come into being, flourish, rise again, begin, come to life, grow, rise from the dead, be immortal, exist, live, survive
difference contrariety, discrimination, distinction, inequality, contrast, disparity, divergence, unlikeness, disagreement, dissimilarity, diversity, variation, discrepancy, dissimilitude, inconsistency, variety agreement, harmony, likeness, sameness, uniformity, consonance, identity, resemblance, similarity, unity
difficult arduous, hard, onerous, toilsome, exhausting, laborious, severe, trying easy, facile, light, pleasant, slight, trifling, trivial
direction aim, bearing, course, inclination, tendency, way
discern behold, discriminate, observe, recognize, descry, distinguish, perceive, see
discover ascertain, detect, disclose, ferret out, find out, descry, discern, expose, find, invent
disease affection, disorder, indisposition, sickness, ailment, distemper, infirmity, unhealthiness, complaint, illness, malady, unsoundness health, robustness, soundness, strength, sturdiness, vigor
disparage belittle, depreciate, discredit, underestimate, carp at, derogate from, dishonor, underrate, decry, detract from, lower, undervalue
displace confuse, derange, disturb, mislay, remove, crowd out, disarrange, jumble, misplace, unsettle adjust, assort, dispose, order, put in order, set in order, array, classify, group, place, put in place, sort
do accomplish, carry out, discharge, perform, achieve, carry through, effect, perpetrate, actualize, commit, execute, realize, bring about, complete, finish, transact, bring to pass, consummate, fulfil, work out baffle, defeat, fail, mar, miss, ruin, come short, destroy, frustrate, miscarry, neglect, spoil
docile amenable, manageable, pliant, teachable, compliant, obedient, submissive, tractable, gentle, pliable, tame, yielding determined, firm, intractable, opinionated, self-willed, wilful, dogged, inflexible, obstinate, resolute, stubborn, unyielding
doctrine article of belief, belief, precept, teaching, article of faith, dogma, principle, tenet
dogmatic arrogant, doctrinal, magisterial, positive, authoritative, domineering, opinionated, self-opinionated, dictatorial, imperious, overbearing, systematic
doubt distrust, mistrust, surmise, suspect believe, confide in, depend on, depend upon, rely on, rely upon, trust
doubt disbelief, incredulity, perplexity, suspense, distrust, indecision, question, suspicion, hesitancy, irresolution, scruple, unbelief, hesitation, misgiving, skepticism, uncertainty assurance, certainty, conviction, determination, resolution, belief, confidence, decision, persuasion, resolve
draw allure, drag, haul, induce, lure, tow, attract, entice, incline, lead, pull, tug alienate, estrange, rebuff, reject, repel, repulse
dream day-dream, fantasy, reverie, trance, fancy, hallucination, romance, vision certainty, fact, reality, realization, substance, verity
dress apparel, clothes, garb, habit, uniform, array, clothing, garments, raiment, vestments, attire, costume, habiliments, robes, vesture bareness, disarray, dishabille, exposure, nakedness, nudity, undress
drive compel, propel, repel, resist, thrust, impel, push, repulse, ride, urge on
duplicate copy, facsimile, likeness, reproduction, counterpart, imitation, replica, transcript archetype, model, original, pattern, prototype
duty accountability, function, office, right, business, obligation, responsibility, righteousness
eager animated, desirous, glowing, importunate, longing, anxious, earnest, hot, intense, vehement, ardent, enthusiastic, impatient, intent, yearning, burning, fervent, impetuous, keen, zealous apathetic, cool, indifferent, regardless, unconcerned, calm, dispassionate, negligent, stolid, uninterested, careless, frigid, phlegmatic, stony, unmindful, cold, heedless, purposeless, stupid, unmoved
ease easiness, expertness, facility, knack, readiness annoyance, constraint, discomfort, irritation, trouble, vexation, awkwardness, difficulty, disquiet, perplexity, uneasiness, worry
education breeding, discipline, learning, study, cultivation, information, nurture, teaching, culture, instruction, reading, training, development, knowledge, schooling, tuition ignorance, illiteracy
effrontery assurance, boldness, hardihood, insolence, audacity, brass, impudence, shamelessness bashfulness, diffidence, sensitiveness, shyness, coyness, modesty, shrinking, timidity
egotism conceit, self-assertion, self-confidence, self-esteem, egoism, self-conceit, self-consciousness, vanity bashfulness, diffidence, modesty, self-forgetfulness, unobtrusiveness, deference, humility, self-distrust, shyness, unostentatiousness
emblem attribute, figure, image, sign, symbol, token, type
emigrate immigrate, migrate
employ call, engage, engross, hire, make use of, use, use up
end break off, close, conclude, expire, quit, terminate, cease, complete, desist, finish, stop, wind up
end accomplishment, effect, limit, achievement, expiration, outcome, bound, extent, period, boundary, extremity, point, cessation, finale, purpose, close, finis, result, completion, finish, termination, conclusion, fulfilment, terminus, consequence, goal, tip, consummation, intent, utmost, design, issue, uttermost
endeavor attempt, essay, strive, try, undertake abandon, give up, omit, throw away, dismiss, let go, overlook, throw over, drop, neglect, pass by, throw up
endeavor attempt, effort, essay, exertion, struggle, trial
endure abide, bear, brook, submit to, sustain, afford, bear up under, permit, suffer, tolerate, allow, bear with, put up with, support, undergo break, despair, fail, fall, give out, sink, surrender, break down, droop, faint, falter, give up, succumb, yield
enemy adversary, antagonist, competitor, foe, opponent, rival abettor, accessory, accomplice, ally, friend, helper, supporter
enmity acrimony, bitterness, ill will, malignity, animosity, hatred, malevolence, rancor, antagonism, hostility, malice, spite agreement, amity, friendship, kindliness, regard, alliance, concord, harmony, kindness, sympathy
entertain amuse, cheer, disport, enliven, interest, please, beguile, delight, divert, gratify, occupy, recreate annoy, bore, busy, disquiet, distract, disturb, tire, weary
entertainment amusement, diversion, fun, pleasure, cheer, enjoyment, merriment, recreation, delight, frolic, pastime, sport ennui, fatigue, labor, lassitude, toil, weariness, work
enthusiasm ardor, excitement, frenzy, transport, devotion, extravagance, inspiration, vehemence, eagerness, fanaticism, intensity, warmth, earnestness, fervency, passion, zeal, ecstasy, fervor, rapture calculation, caution, deadness, indifference, policy, timidity, calmness, coldness, dulness, lukewarmness, prudence, wariness
entrance access, approach, gate, introduction, accession, door, gateway, opening, adit, doorway, ingress, penetration, admission, entrée, inlet, portal, admittance, entry departure, ejection, exit, refusal, withdrawal, egress, exclusion, expulsion, rejection
envious jealous, suspicious contented, friendly, kindly, satisfied, trustful, well-disposed
equivocal ambiguous, enigmatical, indistinct, questionable, doubtful, indefinite, obscure, suspicious, dubious, indeterminate, perplexing, uncertain, enigmatic certain, evident, lucid, perspicuous, unequivocal, clear, indisputable, manifest, plain, unquestionable, distinct, indubitable, obvious, unambiguous, unquestioned
esteem appreciate, consider, estimate, prize, think, calculate, deem, hold, regard, value
esteem estimate, estimation, favor, regard, respect abhorrence, aversion, dislike, loathing, antipathy, contempt, hatred, repugnance
eternal deathless, fadeless, never-failing, undying, endless, immortal, perennial, unending, eonian, imperishable, perpetual, unfading, everlasting, interminable, timeless, unfailing, ever-living, never-ending, unceasing, without end
event case, contingency, fortune, outcome, chance, end, incident, possibility, circumstance, episode, issue, result, consequence, fact, occurrence, sequel
every all, any, both, each, either
evident apparent, glaring, overt, tangible, clear, indubitable, palpable, transparent, conspicuous, manifest, patent, unmistakable, discernible, obvious, perceptible, visible, distinct, open, plain concealed, impalpable, latent, secret, unknown, covert, impenetrable, obscure, undiscovered, unseen, dark, imperceptible, occult, unimagined, unthought-of, hidden, invisible
example archetype, ideal, prototype, type, ensample, model, sample, warning, exemplar, pattern, specimen, exemplification, precedent, standard
excess dissipation, lavishness, redundance, surplus, exorbitance, overplus, redundancy, waste, extravagance, prodigality, superabundance, wastefulness, intemperance, profusion, superfluity dearth, destitution, frugality, lack, scantiness, defect, economy, inadequacy, need, shortcoming, deficiency, failure, insufficiency, poverty, want
execute administer, carry out, do, enforce, perform
exercise act, application, exertion, performance, action, drill, occupation, practise, activity, employment, operation, use idleness, inaction, inactivity, relaxation, rest
expense cost, expenditure, outgo, outlay gain, proceeds, profit, receipt, return, income, product, profits, receipts, returns
explicit ambiguous, implicit, indefinite, uncertain, doubtful, implied, indeterminate, vague
extemporaneous extemporary, impromptu, offhand, extempore, improvised, unpremeditated elaborated, premeditated, prepared, read, recited, studied, written
exterminate annihilate, eradicate, overthrow, uproot, banish, expel, remove, wipe out, destroy, extirpate, root out augment, breed, cherish, develop, increase, populate, replenish, beget, build up, colonize, foster, plant, propagate, settle
faint dim, fatigued, irresolute, weak, exhausted, feeble, languid, wearied, faded, half-hearted, listless, worn, faint-hearted, ill-defined, purposeless, worn down, faltering, indistinct, timid, worn out bright, clear, daring, fresh, resolute, sturdy, brilliant, conspicuous, energetic, hearty, strong, vigorous
faith assent, confidence, credit, opinion, assurance, conviction, creed, reliance, belief, credence, doctrine, trust denial, dissent, doubt, infidelity, rejection, suspicion, disbelief, distrust, incredulity, misgiving, skepticism, unbelief
faithful devoted, incorruptible, stanch, true, trusty, firm, loyal, sure, trustworthy, unwavering capricious, false, unfaithful, untrustworthy, faithless, fickle, untrue, wavering
fame celebrity, eminence, honor, notoriety, reputation, credit, glory, laurels, renown, repute, distinction contempt, discredit, dishonor, humiliation, infamy, obscurity, contumely, disgrace, disrepute, ignominy, oblivion, shame
fanaticism bigotry, credulity, intolerance, superstition cynicism, free-thinking, indifference, latitudinarianism
fanciful chimerical, fantastic, grotesque, imaginative, visionary accurate, commonplace, prosaic, regular, sound, calculable, literal, real, sensible, sure, calculated, ordinary, reasonable, solid, true
fancy belief, desire, imagination, predilection, caprice, humor, inclination, supposition, conceit, idea, liking, vagary, conception, image, mood, whim actuality, certainty, fact, reality, truth, verity
farewell adieu, good-by, parting salutation, valedictory, congé, leave-taking, valediction
fear affright, dismay, horror, timidity, apprehension, disquietude, misgiving, trembling, awe, dread, panic, tremor, consternation, fright, terror, trepidation
feminine effeminate, female, womanish, womanly
fetter bondage, custody, gyves, irons, bonds, durance, handcuffs, manacles, chains, duress, imprisonment, shackles
feud affray, brawl, contest, dissension, hostility, animosity, broil, controversy, enmity, quarrel, bitterness, contention, dispute, fray, strife
fiction allegory, fabrication, invention, myth, romance, apologue, falsehood, legend, novel, story, fable, figment certainty, fact, history, literalness, reality, truth, verity
fierce ferocious, furious, raging, uncultivated, violent, fiery, impetuous, savage, untrained, wild affectionate, gentle, kind, patient, submissive, tame, docile, harmless, mild, peaceful, sweet, tender
financial fiscal, monetary, pecuniary
fine beautiful, excellent, polished, small, clarified, exquisite, pure, smooth, clear, gauzy, refined, splendid, comminuted, handsome, sensitive, subtile, dainty, keen, sharp, subtle, delicate, minute, slender, tenuous, elegant, nice, slight, thin big, clumsy, great, huge, large, stout, blunt, coarse, heavy, immense, rude, thick
fire blaze, burning, combustion, conflagration, flame
flock bevy, covey, group, herd, lot, set, brood, drove, hatch, litter, pack, swarm
fluctuate hesitate, swerve, vacillate, veer, oscillate, undulate, vary, waver abide, adhere, hold fast, persist, stand fast, stay, stick
fluid gas, liquid
follow accompany, come after, go after, obey, pursue, attend, copy, heed, observe, result, chase, ensue, imitate, practise, succeed
food aliment, feed, nourishment, pabulum, sustenance, diet, fodder, nutriment, provender, viands, fare, forage, nutrition, regimen, victuals
formidable dangerous, redoubted, terrible, tremendous contemptible, despicable, feeble, harmless, helpless, powerless, weak
fortification castle, citadel, fastness, fort, fortress, stronghold
fortitude courage, endurance, heroism, resolution
fortunate favored, lucky, prospered, prosperous, successful, happy broken, fallen, miserable, unhappy, woful, crushed, ill-starred, unfortunate, unlucky, wretched
fraud artifice, deceit, duplicity, swindle, treason, cheat, deception, imposition, swindling, trick, cheating, dishonesty, imposture, treachery fairness, good faith, honesty, integrity, truth, uprightness
friendly accessible, companionable, genial, neighborly, affable, complaisant, hearty, sociable, affectionate, cordial, kind, social, amicable, favorable, kindly, tender, brotherly, fond, loving, well-disposed adverse, bellicose, contentious, estranged, ill-disposed, unfriendly, alienated, belligerent, disaffected, frigid, indifferent, unkind, antagonistic, cold, distant, hostile, inimical, warlike
friendship affection, comity, esteem, good will, amity, consideration, favor, love, attachment, devotion, friendliness, regard
frighten affright, appal, cow, dismay, scare, alarm, browbeat, daunt, intimidate, terrify
frugality economy, parsimony, saving, sparing, miserliness, providence, scrimping, thrift, parsimoniousness, prudence abundance, bounty, liberality, opulence, waste, affluence, extravagance, luxury, riches, wealth
garrulous chattering, loquacious, talkative, verbose laconic, reserved, reticent, silent, speechless, taciturn
general common, familiar, ordinary, universal, commonplace, frequent, popular, usual, customary, habitual, prevalent, everyday, normal, public exceptional, infrequent, rare, singular, uncommon, unknown, unusual
generous bountiful, free, liberal, noble, chivalrous, free-handed, magnanimous, open-handed, disinterested, free-hearted, munificent, open-hearted avaricious, covetous, ignoble, mean, niggardly, penurious, rapacious, close, greedy, illiberal, miserly, parsimonious, petty, stingy
genius talent, talents dulness, folly, imbecility, obtuseness, senselessness, stupidity
get achieve, attain, gain, procure, secure, acquire, earn, obtain, receive, win
gift benefaction, boon, bribe, grant, largess, bequest, bounty, donation, gratuity, present compensation, earnings, guerdon, penalty, remuneration wages
give bestow, communicate, deliver, grant, supply, cede, confer, furnish, impart
govern command, curb, influence, mold, reign over, rule, control, direct, manage, reign, restrain, sway be in subjection, be subject, comply, obey, submit, yield
grief affliction, melancholy, regret, sorrow, trouble, distress, mourning, sadness, tribulation, wo
habit custom, habitude, routine, system, use, fashion, practise, rule, usage, wont
happen bechance, chance, fall out, supervene, befall, come to pass, occur, take place, betide, fall
happiness blessedness, delight, gladness, pleasure, bliss, ecstasy, gratification, rapture, cheer, enjoyment, joy, rejoicing, comfort, felicity, merriment, satisfaction, contentment, gaiety, mirth, triumph
happy blessed, cheering, gay, lucky, rejoiced, blissful, cheery, glad, merry, rejoicing, blithe, delighted, jocund, mirthful, smiling, blithesome, delightful, jolly, pleased, sprightly, bright, dexterous, joyful, prosperous, successful, buoyant, felicitous, joyous, rapturous, sunny, cheerful, fortunate
harmony accord, concurrence, consistency, uniformity, accordance, conformity, consonance, union, agreement, congruity, symmetry, unison, amity, consent, unanimity, unity, concord antagonism, contest, discord, hostility, schism, battle, controversy, disproportion, incongruity, separation, conflict, difference, dissension, inconsistency, variance, contention, disagreement, disunion, opposition, warfare
harvest crop, harvest-home, ingathering, result, fruit, harvesting, proceeds, return, growth, harvest-tide, produce, yield, harvest-feast, harvest-time, product, harvest-festival, increase, reaping
hatred abhorrence, detestation, hostility, rancor, anger, dislike, ill will, repugnance, animosity, enmity, malevolence, resentment, antipathy, grudge, malice, revenge, aversion, hate, malignity, spite
have be in possession of, hold, occupy, own, possess, be possessed of
hazard accident, chance, danger, jeopardy, risk, casualty, contingency, fortuity, peril, venture assurance, necessity, protection, safety, surety, certainty, plan, safeguard, security
healthy hale, hygienic, sanitary, vigorous, healthful, salubrious, sound, well, hearty, salutary, strong, wholesome delicate, failing, ill, unsound, worn, diseased, fainting, sick, wasted, worn down, emaciated, fragile, unhealthy, weak, worn out, exhausted, frail
help abet, befriend, foster, succor, uphold, aid, cooperate, second, support, assist, encourage, stand by, sustain counteract, discourage, oppose, resist, thwart, withstand
heretic dissenter, heresiarch, non-conformist, schismatic
heterogeneous confused, mingled, unhomogeneous, conglomerate, miscellaneous, unlike, discordant, mixed, variant, dissimilar, non-homogeneous, various alike, homogeneous, identical, like, pure, same, similar, uniform
hide bury, cover, entomb, overwhelm, suppress, cloak, disguise, inter, screen, veil, conceal, dissemble, mask, secrete admit, disclose, exhume, manifest, show, advertise, discover, expose, promulgate, tell, avow, disinter, lay bare, publish, uncover, betray, divulge, lay open, raise, unmask, confess, exhibit, make known reveal, unveil
high elevated, exalted, noble, steep, towering, eminent, lofty, proud, tall, uplifted base, deep, degraded, depressed, dwarfed, inferior, low, mean, short, stunted
hinder baffle, clog, foil, obstruct, retard, balk, counteract, frustrate, oppose, stay, bar, delay, hamper, prevent, stop, block, embarrass, impede, resist, thwart, check, encumber, interrupt
history account, biography, muniment, record, annals, chronicle, narration, register, archives, memoir, narrative, story, autobiography, memorial, recital
holy blessed, devoted, hallowed, saintly, consecrated, divine, sacred, set apart abominable, cursed, polluted, unconsecrated, unholy, wicked, common, impure, secular, unhallowed, unsanctified, worldly
home abode, dwelling, habitation, hearthstone, ingleside, domicil, fireside, hearth, house, residence
honest candid, frank, ingenuous, true, equitable, genuine, just, trustworthy, fair, good, sincere, trusty, faithful, honorable, straightforward, upright deceitful, faithless, hypocritical, perfidious, unfaithful, dishonest, false, lying, traitorous, unscrupulous, disingenuous, fraudulent, mendacious, treacherous, untrue
horizontal even, flat, level, plain, plane broken, inclined, rolling, rugged, sloping, hilly, irregular, rough, slanting, uneven
humane benevolent, compassionate, human, pitying, benignant, forgiving, kind, sympathetic, charitable, gentle, kind-hearted, tender, clement, gracious, merciful, tender-hearted
hunt chase, hunting, inquisition, pursuit, search
hypocrisy affectation, formalism, pretense, sanctimony, cant, pharisaism, sanctimoniousness, sham, dissimulation, pietism candor, genuineness, ingenuousness, sincerity, truth, frankness, honesty, openness, transparency, truthfulness
hypocrite cheat, deceiver, dissembler, impostor, pretender
hypothesis conjecture, scheme, supposition, system, guess, speculation, surmise, theory certainty, demonstration, discovery, evidence, fact, proof
idea apprehension, design, impression, plan, archetype, fancy, judgment, purpose, belief, fantasy, model, sentiment, conceit, ideal, notion, supposition, concept, image, opinion, theory, conception, imagination, pattern, thought actuality, fact, reality, substance
ideal archetype, model, pattern, prototype, standard, idea, original accomplishment, action, doing, fact, practise, achievement, attainment, embodiment, incarnation, reality, act, development, execution, performance, realization
idiocy fatuity, foolishness, incapacity, stupidity, folly, imbecility, senselessness acuteness, brilliancy, common sense, sagacity, soundness, astuteness, capacity, intelligence, sense, wisdom
idle inactive, inert, slothful, trifling, unoccupied, indolent, lazy, sluggish, unemployed, vacant active, busy, diligent, employed, industrious, occupied, working
ignorant ill-informed, unenlightened, unlearned, untaught, illiterate, uninformed, unlettered, untutored, uneducated, uninstructed, unskilled educated, instructed, learned, sage, skilled, trained, well-informed, wise
imagination fancy, fantasy, phantasy
immediately at once, instanter, presently, straightway, directly, instantly, right away, this instant, forthwith, now, right off, without delay after a while, by and by, hereafter, in the future, some time
immerse bury, dip, douse, duck, immerge, plunge, sink, submerge
imminent impending, threatening chimerical, contingent, doubtful, improbable, problematical, unexpected, unlikely
impediment bar, clog, encumbrance, obstacle, barrier, difficulty, hindrance, obstruction advantage, aid, assistance, benefit, help, relief, succor
impudence assurance, impertinence, intrusiveness, presumption, boldness, incivility, officiousness, rudeness, effrontery, insolence, pertness, sauciness, forwardness bashfulness, diffidence, lowliness, modesty, coyness, humility, meekness, submissiveness
incongruous absurd, ill-matched, inharmonious, conflicting, inapposite, irreconcilable, contradictory, inappropriate, mismatched, contrary, incommensurable, mismated, discordant, incompatible, repugnant, discrepant, inconsistent, unsuitable accordant, agreeing, compatible, consistent, harmonious, suitable
induction deduction, inference
industrious active, busy, employed, occupied, assiduous, diligent, engaged, sedulous
industry application, diligence, labor, persistence, assiduity, effort, pains, sedulousness, attention, exertion, patience, constancy, intentness, perseverance changeableness, idleness, inconstancy, neglect, remissness, fickleness, inattention, indolence, negligence, sloth
infinite absolute, illimitable, limitless, unconditioned, boundless, immeasurable, measureless, unfathomable, countless, innumerable, numberless, unlimited, eternal, interminable, unbounded, unmeasured bounded, finite, measurable, restricted, small, brief, limited, moderate, shallow, transient, circumscribed, little, narrow, short, transitory, evanescent
influence actuate, draw, impel, induce, move, stir, compel, drive, incite, instigate, persuade, sway, dispose, excite, incline, lead, prompt, urge deter, dissuade, impede, prevent, restrain, retard, discourage, hinder, inhibit
inherent congenital, indispensable, innate, native, essential, indwelling, inseparable, natural, immanent, infixed, internal, subjective, inborn, ingrained, intrinsic, inbred, inhering, inwrought accidental, extrinsic, outward, superficial, supplemental, casual, fortuitous, subsidiary, superfluous, transient, external, incidental, superadded, superimposed, unconnected
injury blemish, disadvantage, hurt, loss, prejudice, damage, evil, impairment, mischief, wrong, detriment, harm, injustice, outrage advantage, benefit, boon, improvement, service, amelioration, blessing, help, remedy, utility
injustice grievance, injury, unfairness, unrighteousness, wrong, iniquity equity, faithfulness, impartiality, lawfulness, righteousness, fairness, honesty, integrity, rectitude, uprightness, fair play, honor, justice, right
innocent blameless, guiltless, inoffensive, spotless, clean, harmless, pure, stainless, clear, immaculate, right, upright, faultless, innocuous, righteous, virtuous, guileless, innoxious, sinless
inquisitive curious, meddlesome, peeping, scrutinizing, inquiring, meddling, prying, searching, intrusive apathetic, heedless, indifferent, unconcerned, uninterested, careless, inattentive
insanity aberration, delirium, frenzy, madness, alienation, dementia, hallucination, mania, craziness, derangement, lunacy, monomania clearness, good sense, lucidity, rationality, sanity
interpose arbitrate, intercept, intermeddle, meddle, intercede, interfere, interrupt, mediate avoid, keep aloof, keep out, retire, stand back, hold aloof, keep away, let alone, stand aside, stand off, hold off, keep clear, let be, stand away, withdraw
involve complicate, embroil, implicate, include, embarrass, entangle, imply, overwhelm disconnect, disentangle, distinguish, explicate, extricate, remove, separate
journey excursion, pilgrimage, transit, trip, expedition, tour, travel, voyage
judge arbiter, arbitrator, justice, referee, umpire
justice equity, impartiality, legality, rightfulness, fairness, integrity, rectitude, truth, fair play, justness, right, uprightness, faithfulness, law, righteousness, virtue, honor, lawfulness dishonesty, inequity, partiality, unlawfulness, untruth, favoritism, injustice, unfairness, unreasonableness, wrong
keep carry, defend, hold, preserve, retain, carry on, detain, maintain, protect, support, celebrate, fulfil, obey, refrain, sustain, conduct, guard, observe, restrain, withhold
kill assassinate, despatch, massacre, put to death, slay, butcher, execute, murder, slaughter
kin affinity, blood, descent, kind, race, alliance, consanguinity, family, kindred, relationship, birth
knowledge acquaintance, erudition, learning, recognition, apprehension, experience, light, scholarship, cognition, information, lore, science, cognizance, intelligence, perception, wisdom, comprehension, intuition ignorance, inexperience, misconception, rudeness, illiteracy, misapprehension, misunderstanding, unfamiliarity
language barbarism, expression, patois, vernacular, dialect, idiom, speech, vocabulary, diction, mother tongue, tongue
large abundant, coarse, gigantic, long, ample, colossal, grand, massive, big, commodious, great, spacious, broad, considerable, huge, vast, bulky, enormous, immense, wide, capacious, extensive brief, infinitesimal, little, minute, petty, slender, tiny, diminutive, insignificant, mean, narrow, scanty, slight, trifling, inconsiderable, limited, microscopic, paltry, short, small, trivial
law canon, economy, legislation, principle, code, edict, mandate, regulation, command, enactment, order, rule, commandment, formula, ordinance, statute, decree, jurisprudence, polity
liberty emancipation, freedom, independence, license captivity, imprisonment, oppression, slavery, compulsion, necessity, serfdom, superstition, constraint, obligation, servitude, thraldom
light blaze, gleam, glow, shimmer, flame, gleaming, illumination, shine, flare, glimmer, incandescence, shining, flash, glistening, luster, sparkle, flicker, glistering, scintillation, twinkle, glare, glitter, sheen, twinkling blackness, darkness, dusk, gloominess, shade, dark, dimness, gloom, obscurity, shadow
likely apt, conceivable, liable, probable, credible, conjectural, presumable, reasonable doubtful, improbable, questionable, unreasonable, dubious, incredible, unlikely
listen attend, hark, harken, hear, heed, list be deaf to, ignore, neglect, scorn, slight
literature belles-lettres, literary productions, publications, books, literary works, writings
load burden, charge, encumbrance, incubus, pack, cargo, clog, freight, lading, weight
lock bar, catch, fastening, hook, bolt, clasp, hasp, latch
look behold, discern, inspect, see, view, contemplate, gaze, regard, stare, watch, descry, glance, scan, survey
love affection, charity, friendship, regard, attachment, devotion, liking, tenderness, attraction, fondness
make become, constrain, fabricate, manufacture, bring about, construct, fashion, occasion, bring into being, create, force, perform, bring to pass, do, frame, reach, cause, effect, get, render, compel, establish, make out, require, compose, execute, make up, shape, constitute
marriage conjugal union, espousals, nuptials, spousals, wedding, espousal, matrimony, spousal, union, wedlock bachelorhood, celibacy, divorce, maidenhood, virginity, widowhood
masculine male, manful, manlike, manly, mannish, virile
massacre butchery, carnage, havoc, slaughter
meddlesome impertinent, intrusive, meddling, obtrusive, officious modest, reserved, retiring, shy, unassuming, unobtrusive
melody harmony, music, symphony, unison
memory recollection, reminiscence, retrospect, retrospection, remembrance forgetfulness, oblivion, obliviousness, oversight, unconsciousness
mercy benevolence, favor, kindness, mildness, benignity, forbearance, lenience, pardon, blessing, forgiveness, leniency, pity, clemency, gentleness, lenity, tenderness, compassion, grace cruelty, implacability, punishment, rigor, sternness, hardness, justice, revenge, severity, vengeance, harshness, penalty
meter euphony, measure, rhythm, verse
mind brain, instinct, reason, spirit, consciousness, intellect, sense, thought, disposition, intelligence, soul, understanding body, brawn, brute force, material substance, matter
minute circumstantial, diminutive, little, slender, comminuted, exact, particular, small, critical, fine, precise, tiny, detailed
misfortune adversity, disappointment, ill fortune, ruin, affliction, disaster, ill luck, sorrow, bereavement, distress, misadventure, stroke, blow, failure, mischance, trial, calamity, hardship, misery, tribulation, chastening, harm, mishap, trouble, chastisement, ill, reverse, visitation blessing, consolation, gratification, pleasure, success, boon, good fortune, happiness, prosperity, triumph, comfort, good luck, joy, relief
mob canaille, dregs of the people, masses, rabble, crowd, lower classes, populace, the vulgar
model archetype, facsimile, original, representation, copy, image, pattern, standard, design, imitation, prototype, type, example, mold
modesty backwardness, constraint, reserve, timidity, bashfulness, coyness, shyness, unobtrusiveness, coldness, diffidence abandon, boldness, forwardness, impudence, pertness, sociability, arrogance, conceit, frankness, indiscretion, sauciness, assumption, confidence, freedom, loquaciousness, self-conceit, assurance, egotism, haughtiness, loquacity, self-sufficiency
money bills, cash, funds, property, bullion, coin, gold, silver, capital, currency, notes, specie
morose acrimonious, dogged, ill-natured, splenetic, churlish, gloomy, severe, sulky, crabbed, gruff, snappish, sullen, crusty, ill-humored, sour, surly amiable, complaisant, gentle, kind, pleasant, benignant, friendly, good-natured, loving, sympathetic, bland, genial, indulgent, mild, tender
motion act, change, movement, process, transition, action, move, passage, transit immobility, quiescence, quiet, repose, rest, stillness
mourn bemoan, deplore, lament, regret, rue, sorrow, bewail, grieve be joyful, exult, joy, make merry, rejoice, triumph
mutual common, correlative, interchangeable, joint, reciprocal detached, distinct, separate, severed, unconnected, unrequited, disconnected, disunited, separated, sundered, unreciprocated, unshared, dissociated
mysterious abstruse, inexplicable, recondite, cabalistic, inscrutable, secret, dark, mystic, transcendental, enigmatical, mystical, unfathomable, hidden, obscure, unfathomed, incomprehensible, occult, unknown
name agnomen, denomination, prenomen, surname, appellation, designation, style, title, cognomen, epithet
native indigenous, innate, natal, natural, original acquired, alien, artificial, assumed, foreign, unnatural
nautical marine, maritime, naval, ocean, oceanic
neat clean, dapper, nice, prim, tidy, cleanly, natty, orderly, spruce, trim dirty, negligent, slouchy, uncared for, disorderly, rough, slovenly, unkempt, dowdy, rude, soiled, untidy
necessary essential, infallible, required, unavoidable, indispensable, needed, requisite, undeniable, inevitable, needful casual, needless, optional, useless, contingent, non-essential, unnecessary, worthless
necessity compulsion, fatality, requisite, destiny, fate, sine qua non, emergency, indispensability, unavoidableness, essential, indispensableness, urgency, exigency, need, want, extremity, requirement choice, doubt, dubiousness, freedom, possibility, contingency, doubtfulness, fortuity, option, uncertainty
neglect carelessness, heedlessness, negligence, scorn, default, inadvertence, omission, slackness, disregard, inattention, oversight, slight, disrespect, indifference, remissness, thoughtlessness, failure, neglectfulness
new fresh, modern, new-made, upstart, juvenile, new-fangled, novel, young, late, new-fashioned, recent, youthful
nimble active, alert, bustling, prompt, speedy, spry, agile, brisk, lively, quick, sprightly, swift clumsy, dilatory, dull, heavy, inactive, inert, slow, sluggish, unready
normal common, natural, ordinary, regular, typical, usual abnormal, irregular, peculiar, singular, unprecedented, exceptional, monstrous, rare, uncommon, unusual
notwithstanding altho(ugh), howbeit, nevertheless, tho(ugh), but, however, still, yet
notwithstanding despite, in spite of
oath adjuration, curse, profane swearing, affidavit, cursing, profanity, anathema, denunciation, reprobation, ban, execration, swearing, blaspheming, imprecation, sworn statement, blasphemy, malediction, vow benediction, benison, blessing
obscure abstruse, darksome, dusky, involved, ambiguous, deep, enigmatical, muddy, cloudy, dense, hidden, mysterious, complex, difficult, incomprehensible, profound, complicated, dim, indistinct, turbid, dark, doubtful, intricate, unintelligible
obsolete ancient, archaic, obsolescent, out of date, antiquated, disused, old, rare
obstinate contumacious, headstrong, mulish, resolute, decided, heady, obdurate, resolved, determined, immovable, opinionated, stubborn, dogged, indomitable, persistent, unconquerable, firm, inflexible, pertinacious, unflinching, fixed, intractable, refractory, unyielding amenable, dutiful, pliable, tractable, complaisant, gentle, pliant, undecided, compliant, irresolute, submissive, wavering, docile, obedient, teachable, yielding
obstruct arrest, check, embarrass, interrupt, stay, bar, choke, hinder, oppose, stop, barricade, clog, impede, retard accelerate, aid, facilitate, free, open, promote, advance, clear, forward, further, pave the way for
old aged, decrepit, immemorial, senile, ancient, elderly, olden, time-honored, antiquated, gray, patriarchal, time-worn, antique, hoary, remote, venerable
operation action, effect, force, performance, result, agency, execution, influence, procedure failure, ineffectiveness, inutility, powerlessness, uselessness, inaction, inefficiency
order command, injunction, mandate, requirement, direction, instruction, prohibition allowance, consent, leave, liberty, license, permission, permit
ostentation boast, flourish, parade, pompousness, vaunt, boasting, pageant, pomp, show, vaunting, display, pageantry, pomposity diffidence, quietness, retirement, timidity, modesty, reserve, shrinking, unobtrusiveness
oversight care, control, management, surveillance, charge, direction, superintendence, watch, command, inspection, supervision, watchfulness
pain ache, distress, suffering, torture, agony, pang, throe, twinge, anguish, paroxysm, torment, wo(e) comfort, delight, ease, enjoyment, peace, rapture, relief, solace
palliate apologize for, conceal, extenuate, hide, screen, cloak, cover, gloss over, mitigate, veil
pardon absolve, condone, forgive, pass by, remit, acquit, excuse, overlook, pass over castigate, chastise, convict, doom, recompense, sentence, chasten, condemn, correct, punish, scourge, visit
pardon absolution, amnesty, forgiveness, oblivion, acquittal, forbearance, mercy, remission penalty, punishment, retaliation, retribution, vengeance
part atom, fraction, member, section, component, fragment, particle, segment, constituent, ingredient, piece, share, division, instalment, portion, subdivision, element
particle atom, grain, mite, scrap, whit, corpuscle, iota, molecule, shred, element, jot, scintilla, tittle aggregate, entirety, mass, quantity, sum, sum total, total, whole
patience calmness, forbearance, long-suffering, sufferance, composure, fortitude, resignation, endurance, leniency, submission
pay allowance, hire, recompense, salary, compensation, honorarium, remuneration, stipend, earnings, payment, requital, wages, fee
people commonwealth, nation, race, state, tribe, community, population
perceive apprehend, comprehend, conceive, understand fail of, ignore, lose, misapprehend, misconceive, miss, overlook
perfect absolute, consummate, holy, spotless, accurate, correct, ideal, stainless, blameless, entire, immaculate, unblemished, complete, faultless, sinless, undefiled, completed, finished bad, defective, imperfect, meager, scant, blemished, deficient, incomplete, perverted, short, corrupt, deformed, inferior, poor, spoiled, corrupted, fallible, insufficient, ruined, worthless, defaced, faulty, marred
permanent abiding, enduring, lasting, steadfast, changeless, fixed, perpetual, unchangeable, constant, immutable, persistent, unchanging, durable, invariable, stable
permission allowance, authorization, leave, license, authority, consent, liberty, permit denial, objection, prevention, refusal, resistance, hindrance, opposition, prohibition
pernicious bad, evil, mischievous, pestilential, baneful, foul, noisome, poisonous, deadly, harmful, noxious, ruinous, deleterious, hurtful, perverting, unhealthful, destructive, injurious, pestiferous, unwholesome, detrimental, insalubrious advantageous, favorable, helpful, profitable, serviceable, beneficent, good, invigorating, rejuvenating, useful, beneficial, healthful, life-giving, salutary, wholesome
perplexity amazement, bewilderment, distraction, doubt, astonishment, confusion, disturbance, embarrassment
persuade allure, dispose, incline, move, bring over, entice, induce, prevail on or upon, coax, impel, influence, urge, convince, incite, lead, win over deter, discourage, dissuade, hinder, hold back, repel, restrain
pertness boldness, forwardness, liveliness, sprightliness, briskness, impertinence, sauciness, flippancy, impudence, smartness bashfulness, demureness, diffidence, humility, modesty, shyness
perverse contrary, froward, petulant, untoward, factious, intractable, stubborn, wayward, fractious, obstinate, ungovernable, wilful accommodating, complaisant, genial, kind, amenable, compliant, governable, obliging
physical bodily, corporeal, natural, tangible, corporal, material, sensible, visible hyperphysical, intangible, invisible, moral, unreal, immaterial, intellectual, mental, spiritual, unsubstantial
pique displeasure, irritation, offense, resentment, umbrage, grudge approval, contentment, delight, gratification, pleasure, satisfaction, complacency
pitiful abject, lamentable, paltry, sorrowful, base, miserable, pathetic, touching, contemptible, mournful, piteous, woful, despicable, moving, pitiable, wretched august, dignified, grand, lofty, sublime, beneficent, exalted, great, mighty, superb, commanding, glorious, helpful, noble, superior
pity commiseration, condolence, sympathy, tenderness, compassion, mercy barbarity, ferocity, harshness, pitilessness, severity, brutality, hard-heartedness, inhumanity, rigor, sternness, cruelty, hardness, mercilessness, ruthlessness, truculence
plant seed, seed down, set, set out, sow eradicate, extirpate, root up, uproot, weed out
plead advocate, ask, beseech, implore, solicit, argue, beg, entreat, press, urge
pleasant agreeable, good-natured, kindly, pleasing, attractive, kind, obliging, pleasurable arrogant, displeasing, glum, ill-humored, repelling, austere, dreary, grim, ill-natured, repulsive, crabbed, forbidding, harsh, offensive, unkind, disagreeable, gloomy, hateful, repellent, unpleasant
plentiful abounding, bountiful, generous, plenteous, abundant, complete, large, profuse, adequate, copious, lavish, replete, affluent, enough, liberal, rich, ample, exuberant, luxuriant, sufficient, bounteous, full, overflowing, teeming deficient, inadequate, narrow, scanty, small, drained, insufficient, niggardly, scarce, sparing, exhausted, mean, poor, scrimped, stingy, impoverished, miserly, scant, short, straitened
poetry meter, numbers, poesy, song, metrical composition, poem, rime, verse prosaic speech, prosaic writing, prose
polite accomplished, courtly, genteel, urbane, civil, cultivated, gracious, well-behaved, complaisant, cultured, obliging, well-bred, courteous, elegant, polished, well-mannered awkward, clownish, ill-mannered, insulting, uncouth, bluff, coarse, impertinent, raw, unmannerly, blunt, discourteous, impolite, rude, unpolished, boorish, ill-behaved, impudent, rustic, untaught, brusk, ill-bred, insolent, uncivil, untutored
polity constitution, policy, form or system of government
portion lot, parcel, part, proportion, share
poverty beggary, distress, mendicancy, pauperism, privation, destitution, indigence, need, penury, want
power ability, competency, expertness, readiness, aptitude, dexterity, faculty, skill, capability, efficacy, force, strength, capacity, efficiency, might, susceptibility, cleverness, energy, qualification, talent, cogency awkwardness, helplessness, inability, incompetence, stupidity, dulness, imbecility, inaptitude, inefficiency, unskilfulness, feebleness, impotence, incapacity, maladroitness, weakness
praise acclaim, approbation, compliment, laudation, acclamation, approval, encomium, panegyric, adulation, cheering, eulogy, plaudit, applause, cheers, flattery, sycophancy abuse, condemnation, disapproval, obloquy, scorn, animadversion, contempt, disparagement, reproach, slander, blame, denunciation, hissing, reproof, vilification, censure, disapprobation, ignominy, repudiation, vituperation
pray ask, bid, entreat, invoke, request, beg, call upon, implore, petition, supplicate, beseech, conjure, importune, plead
precarious doubtful, hazardous, risky, unsettled, dubious, insecure, unassured, unstable, equivocal, perilous, uncertain, unsteady actual, firm, infallible, stable, sure, undoubted, assured, immutable, real, steady, undeniable, unquestionable, certain, incontestable, settled, strong
precedent antecedent, case, instance, pattern, authority, example, obiter dictum, warrant
predestination fate, foreknowledge, foreordination, necessity accident, choice, freedom, independence, chance, free agency, free will, uncertainty
prejudice bias, preconception, presumption, partiality, prepossession, unfairness certainty, conviction, evidence, reason, conclusion, demonstration, proof, reasoning
pretense affectation, disguise, pretext, simulation, air, dissimulation, ruse, subterfuge, assumption, excuse, seeming, trick, cloak, mask, semblance, wile, color, pretension, show actuality, fact, guilelessness, ingenuousness, reality, sincerity, candor, frankness, honesty, openness, simplicity, truth
prevent anticipate, forestall, obviate, preclude
previous antecedent, foregoing, front, preceding, anterior, former, introductory, preliminary, earlier, forward, precedent, prior after, consequent, hind, hindmost, latter, subsequent, concluding, following, hinder, later, posterior, succeeding
price charge, cost, expenditure, expense, outlay, value, worth
pride arrogance, ostentation, self-exaltation, assumption, presumption, self-respect, conceit, reserve, superciliousness, disdain, self-complacency, vainglory, haughtiness, self-conceit, vanity, insolence, self-esteem humility, lowliness, meekness, modesty, self-abasement, self-distrust
primeval aboriginal, indigenous, patriarchal, primitive, ancient, native, primal, primordial, autochthonic, old, primary, pristine, immemorial, original, prime, uncreated adventitious, foreign, late, new, recent, exotic, fresh, modern, novel
profit advantage, expediency, proceeds, service, avail, gain, receipts, usefulness, benefit, good, return, utility, emolument, improvement, returns, value damage, detriment, harm, injury, ruin, destruction, disadvantage, hurt, loss, waste
progress advance, development, improvement, proficiency, advancement, growth, increase, progression, attainment check, delay, falling off, retrogression, stop, decline, falling back, relapse, stay, stoppage
prohibit debar, forbid, inhibit, preclude, disallow, hinder, interdict, prevent allow, empower, let, require, authorize, enjoin, license, sanction, command, give consent, order, suffer, consent to, give leave, permit, tolerate, direct, give permission, put up with, warrant
promote advance, encourage, forward, prefer, raise, aid, exalt, foster, push, urge forward, assist, excite, further, push on, urge on, elevate, foment, help
propitiation atonement, expiation, reconciliation, satisfaction alienation, curse, penalty, reprobation, vengeance, chastisement, estrangement, punishment, retribution, wrath, condemnation, offense
propitious auspicious, benignant, favorable, gracious, kindly, benign, clement, friendly, kind, merciful adverse, forbidding, ill-disposed, repellent, unfriendly, antagonistic, hostile, inauspicious, unfavorable, unpropitious
proposal bid, offer, overture, proposition acceptance, denial, disapproval, refusal, rejection, repulse
propose
protract continue, delay, elongate, lengthen, procrastinate, defer, draw out, extend, postpone, prolong abbreviate, conclude, curtail, hurry, reduce, abridge, contract, hasten, limit, shorten
proverb adage, axiom, maxim, saw, aphorism, byword, motto, saying, apothegm, dictum, precept, truism
prowess bravery, gallantry, intrepidity, courage, heroism, valor cowardice, cowardliness, effeminacy, fear, pusillanimity, timidity
prudence care, discretion, judgment, carefulness, forecast, judiciousness, caution, foresight, providence, circumspection, forethought, wisdom, consideration, frugality folly, improvidence, indiscretion, rashness, thoughtlessness, heedlessness, imprudence, prodigality, recklessness, wastefulness
purchase acquire, barter for, get, procure, secure, bargain for, buy, obtain barter, dispose of, exchange, put to sale, sell
pure absolute, guiltless, simple, unmixed, chaste, holy, spotless, unpolluted, classic, immaculate, stainless, unspotted, classical, incorrupt, true, unstained, clean, innocent, unadulterated, unsullied, clear, mere, unblemished, untainted, continent, perfect, uncorrupted, untarnished, genuine, real, undefiled, upright, guileless, sheer, unmingled, virtuous adulterated, foul, indecent, obscene, tainted, defiled, gross, indelicate, polluted, tarnished, dirty, immodest, lewd, stained, unchaste, filthy, impure, mixed, sullied, unclean
put deposit, lay, place, set
queer anomalous, erratic, odd, strange, bizarre, extraordinary, peculiar, uncommon, comical, fantastic, preposterous, unique, crotchety, funny, quaint, unmatched, curious, grotesque, ridiculous, unusual, droll, laughable, singular, whimsical, eccentric, ludicrous common, familiar, normal, regular, customary, natural, ordinary, usual
quicken accelerate, drive on, hasten, promote, advance, expedite, hurry, speed, despatch, facilitate, make haste, urge, drive, further, press forward, urge on check, clog, delay, drag, hinder, impede, obstruct, retard
quote cite, extract, plagiarize, repeat, excerpt, paraphrase, recite
racy flavorous, lively, pungent, spicy, forcible, piquant, rich, spirited cold, flat, insipid, stale, tasteless, dull, flavorless, prosy, stupid, vapid
radical complete, ingrained, perfect, constitutional, innate, positive, entire, native, primitive, essential, natural, thorough, extreme, organic, thoroughgoing, fundamental, original, total conservative, incomplete, palliative, slight, tentative, inadequate, moderate, partial, superficial, trial
rare curious, odd, scarce, unique, extraordinary, peculiar, singular, unparalleled, incomparable, precious, strange, unprecedented, infrequent, remarkable, uncommon, unusual
reach arrive, attain, come to, enter, gain, get to, land depart, embark, go, go away, leave, set out, set sail, start, weigh anchor
real actual, demonstrable, genuine, true, authentic, developed, positive, unquestionable, certain, essential, substantial, veritable conceived, feigned, illusory, supposed, unreal, fabulous, fictitious, imaginary, supposititious, untrue, fanciful, hypothetical, reported, theoretical, visionary
reason argue, debate, discuss, establish, question, contend, demonstrate, dispute, prove, wrangle, controvert
reason account, cause, end, motive, principle, aim, consideration, ground, object, purpose, argument, design
reasoning argument, argumentation, debate, ratiocination
rebellious contumacious, mutinous, uncontrollable, disobedient, refractory, ungovernable, insubordinate, seditious, unmanageable, intractable compliant, docile, manageable, subservient, controllable, dutiful, obedient, tractable, deferential, gentle, submissive, yielding
record account, enrolment, instrument, register, archive, entry, inventory, roll, catalogue, enumeration, memorandum, schedule, chronicle, history, memorial, scroll, document, inscription, muniment
recover be cured or healed, heal, recuperate, restore, be restored, reanimate, regain, resume, cure, recruit, repossess, retrieve die, fail, grow worse, relapse, sink
refinement civilization, cultivation, culture, elegance, politeness barbarism, brutality, coarseness, rudeness, savagery, boorishness, clownishness, grossness, rusticity, vulgarity
refute confound, confute, disprove, overthrow, repel
reliable trustworthy, trusty
religion devotion, godliness, morality, piety, theology, faith, holiness, pietism, righteousness, worship atheism, godlessness, irreligion, sacrilege, ungodliness, blasphemy, impiety, profanity, unbelief, wickedness
reluctant averse, disinclined, loath, slow, backward, indisposed, opposed, unwilling desirous, disposed, eager, favorable, inclined, willing
remark annotation, comment, note, observation, utterance
rend break, cleave, mangle, rive, sever, sunder, burst, lacerate, rip, rupture, slit, tear heal, join, mend, reunite, secure, sew, solder, stitch, unite, weld
renounce abandon, disavow, disown, recant, repudiate, abjure, discard, forswear, refuse, retract, deny, disclaim, recall, reject, revoke acknowledge, assert, cherish, defend, maintain, proclaim, uphold, advocate, avow, claim, hold, own, retain, vindicate
repentance compunction, contriteness, regret, self-condemnation, contrition, penitence, remorse, sorrow approval, content, obduracy, self-complacency, comfort, hardness, obstinacy, self-congratulation, complacency, impenitence, self-approval, stubbornness
report account, narrative, rehearsal, rumor, story, description, recital, relation, statement, tale, narration, record
reproof admonition, chiding, disapproval, reprimand, animadversion, comment, objurgation, reproach, blame, condemnation, rebuke, reproval, censure, criticism, reflection, upbraiding, check, denunciation, reprehension applause, approval, encomium, eulogy, panegyric, praise, approbation, commendation
reprove admonish, condemn, reprimand, blame, expostulate with, reproach, censure, find fault with, take to task, chasten, rebuke, upbraid, check, remonstrate with, warn, chide, reprehend abet, approve, countenance, impel, instigate, applaud, cheer, encourage, incite, urge on
requite avenge, punish, remunerate, revenge, compensate, quit, repay, reward, pay, reciprocate, retaliate, satisfy, pay off, recompense, return, settle with absolve, excuse, forgive, overlook, pass over, acquit, forget, neglect, pardon, slight
rest calm, pause, quietness, slumber, calmness, peace, quietude, stay, cessation, peacefulness, recreation, stillness, ease, quiescence, repose, stop, intermission, quiet, sleep, tranquillity agitation, disturbance, movement, stir, tumult, commotion, excitement, restlessness, strain, unrest, disquiet, motion, rush, toil, work
restive balky, impatient, rebellious, restless, fidgety, intractable, recalcitrant, skittish, fractious, mulish, refractory, stubborn, fretful, mutinous, resentful, unruly, frisky, obstinate, restiff, vicious docile, manageable, passive, quiet, tractable, gentle, obedient, peaceable, submissive, yielding
restrain abridge, constrain, hold in, keep under, bridle, curb, keep, repress, check, hinder, keep back, restrict, circumscribe, hold, keep down, suppress, confine, hold back, keep in, withhold aid, arouse, encourage, free, incite, release, animate, emancipate, excite, impel, let loose, set free
retirement loneliness, privacy, seclusion, solitude association, companionship, company, converse, fellowship, society
revelation apocalypse, disclosure, manifestation cloud, concealment, mystery, shrouding, cloudiness, hiding, obscuration, veiling
revenge avenging, retaliation, retribution, vengeance, requital compassion, forgiveness, mercy, pardon, pity, reconciliation, excuse, grace
revolution anarchy, insurrection, revolt, confusion, lawlessness, riot, disintegration, mutiny, sedition, disorder, rebellion, tumult, insubordination authority, domination, government, obedience, sovereignty, command, dominion, law, order, submission, control, empire, loyalty, rule, supremacy
revolve roll, rotate, turn bind, chafe, grind, slide, slip, stand, stick
riddle conundrum, enigma, paradox, problem, puzzle answer, axiom, explanation, proposition, solution
right claim, franchise, liberty, prerogative, exemption, immunity, license, privilege
rise arise, ascend, emanate, flow, issue, proceed, spring decline, descend, drop, fall, go down, set, settle, sink
robber bandit, depredator, freebooter, pirate, brigand, despoiler, highwayman, plunderer, buccaneer, footpad, marauder, raider, burglar, forager, pillager, thief
royal august, kingly, majestic, princely, kinglike, magnificent, munificent, regal beggarly, contemptible, mean, poor, servile, slavish, vile
rustic agricultural, coarse, pastoral, uncouth, artless, countrified, plain, unpolished, awkward, country, rude, unsophisticated, boorish, hoidenish, rural, untaught, bucolic, inelegant, sylvan, verdant, clownish, outlandish accomplished, cultured, polished, refined, urbane, city-like, elegant, polite, urban, well-bred
sacrament ceremony, eucharist, observance, rite, solemnity, communion, Lord's Supper, ordinance, service
sagacious able, intelligent, perspicacious, sensible, acute, keen, quick of scent, sharp, apt, keen-sighted, quick-scented, sharp-witted, clear-sighted, keen-witted, rational, shrewd, discerning, judicious, sage, wise absurd, foolish, ignorant, obtuse, silly, sottish, undiscerning, dull, futile, irrational, senseless, simple, stupid, unintelligent
sale bargain, barter, change, deal, exchange, trade
sample case, exemplification, instance, example, illustration, specimen abnormality, aggregate, exception, monstrosity, total, whole
satisfy cloy, fill, sate, suffice, content, glut, satiate, surfeit check, disappoint, restrain, starve, straiten, deny, refuse, restrict, stint, tantalize
scholar disciple, learner, pupil, savant, student dunce, fool, idiot, idler, ignoramus, illiterate person
science art, knowledge
security bail, earnest, gage, pledge, surety
self-abnegation self-control, self-devotion, self-renunciation, self-denial, self-immolation, self-sacrifice self-gratification, self-indulgence, selfishness, self-seeking, self-will
send cast, despatch, emit, impel, propel, dart, discharge, fling, lance, sling, delegate, dismiss, forward, launch, throw, depute, drive, hurl, project, transmit bring, convey, give, hold, receive, carry, get, hand, keep, retain
sensation emotion, feeling, perception, sense
sensibility feeling, impressibility, sensitiveness, susceptibility coldness, deadness, hardness, insensibility, numbness, unconsciousness
severe austere, inflexible, rigorous, uncompromising, hard, morose, stern, unmitigated, harsh, relentless, stiff, unrelenting, inexorable, rigid, strict, unyielding affable, easy, gentle, lenient, pliable, sweet, tractable, bland, genial, indulgent, mild, soft, tender, yielding
shake agitate, jar, quake, shiver, totter, brandish, joggle, quaver, shudder, tremble, flap, jolt, quiver, sway, vibrate, fluctuate, jounce, reel, swing, wave, flutter, oscillate, rock, thrill, waver
shelter cover, guard, protect, shield, defend, harbor, screen, ward betray, cast out, expel, expose, give up, refuse, reject, surrender
sign emblem, mark, presage, symbol, token, indication, note, prognostic, symptom, type, manifestation, omen, signal
sin crime, fault, misdeed, vice, criminality, guilt, offense, viciousness, delinquency, ill-doing, transgression, wickedness, depravity, immorality, ungodliness, wrong, evil, iniquity, unrighteousness, wrong-doing blamelessness, goodness, integrity, rectitude, sinlessness, excellence, holiness, morality, right, uprightness, godliness, innocence, purity, righteousness, virtue
sing carol, chant, chirp, chirrup, hum, warble
skeptic agnostic, deist, doubter, infidel, unbeliever, atheist, disbeliever, freethinker believer, Christian
sketch brief, draft, outline, plan, design, drawing, picture, skeleton
skilful accomplished, apt, dexterous, happy, proficient, adept, clever, expert, ingenious, skilled, adroit, deft, handy, practised, trained awkward, clumsy, inexpert, shiftless, unskilled, untrained, bungling, helpless, maladroit, unhandy, untaught
slander asperse, decry, disparage, revile, backbite, defame, libel, traduce, calumniate, depreciate, malign, vilify defend, eulogize, extol, laud, praise, vindicate
slang cant, colloquialism, vulgarism, vulgarity
slow dawdling, dilatory, gradual, lingering, slack, delaying, drowsy, inactive, moderate, sluggish, deliberate, dull, inert, procrastinating, tardy
sneer fling, gibe, jeer, mock, scoff, taunt
socialism collectivism, communism, fabianism
sound noise, note, tone
speak announce, converse, discourse, say, articulate, declaim, enunciate, talk, chat, declare, express, tell, chatter, deliver, pronounce, utter
speech address, dissertation, oration, speaking, discourse, harangue, oratory, talk, disquisition, language, sermon, utterance hush, silence, speechlessness, stillness, taciturnity
spontaneous automatic, impulsive, involuntary, voluntary, free, instinctive, unbidden, willing
spy detective, emissary, scout
stain blot, discolor, dishonor, soil, sully, tinge, color, disgrace, dye, spot, tarnish, tint
state affirm, aver, declare, predicate, set forth, allege, avouch, depose, pronounce, specify, assert, avow, express, propound, swear, asseverate, certify, inform, protest, tell, assure, claim, maintain, say, testify contradict, controvert, disprove, gainsay, refute, retract, contravene, deny, dispute, oppose, repudiate, waive
steep abrupt, high, precipitous, sharp, sheer easy, flat, gentle, gradual, horizontal, level, low, slight
storm agitation, disturbance, tempest calm, fair weather, hush, peace, serenity, stillness, tranquillity
story account, legend, narrative, recital, relation, anecdote, myth, novel, record, tale, incident, narration annals, biography, chronicle, history, memoir
stupidity apathy, insensibility, slowness, stupefaction, dulness, obtuseness, sluggishness, stupor acuteness, brilliancy, keenness, sagacity, alertness, cleverness, quickness, sense, animation, intelligence, readiness, sensibility
stupor apathy, fainting, stupefaction, syncope, asphyxia, insensibility, swoon, torpor, coma, lethargy, swooning, unconsciousness
subsidy aid, bounty, indemnity, reward, support, allowance, gift, pension, subvention, tribute, bonus, grant, premium
subvert destroy, overthrow, ruin, supplant, extinguish, overturn, supersede, suppress conserve, keep, perpetuate, preserve, sustain, uphold
succeed achieve, attain, flourish, prevail, prosper, thrive, win be defeated, come short, fail, fall short, lose, miss, miscarry
suggestion hint, implication, innuendo, insinuation, intimation
supernatural miraculous, preternatural, superhuman common, commonplace, everyday, natural, ordinary, usual
support bear, cherish, keep, maintain, sustain, carry, hold up, keep up, prop, uphold abandon, break down, demolish, destroy, let go, throw down, betray, cast down, desert, drop, overthrow, wreck
suppose conjecture, deem, guess, imagine, surmise, think ascertain, be sure, conclude, discover, know, prove
surrender abandon, cede, give over, relinquish, alienate, give, give up, sacrifice, capitulate, give oneself up, let go, yield
synonymous alike, equivalent, like, similar, correspondent, identical, same, synonymic, corresponding, interchangeable
system manner, method, mode, order, regularity, rule chaos, derangement, disarrangement, disorder, irregularity, confusion
taciturn close, mute, reticent, speechless, dumb, reserved, silent, uncommunicative communicative, free, garrulous, loquacious, talkative, unreserved
tasteful artistic, delicate, esthetic, fastidious, nice, chaste, delicious, esthetical, fine, tasty, dainty, elegant, exquisite clumsy, displeasing, grotesque, inartistic, rough, coarse, distasteful, harsh, inharmonious, rude, deformed, fulsome, hideous, meretricious, rugged, disgusting, gaudy, horrid, offensive, tawdry
teach discipline, give instruction, inform, nurture, drill, give lessons, initiate, school, educate, inculcate, instill, train, enlighten, indoctrinate, instruct, tutor
temerity audacity, heedlessness, presumption, foolhardiness, over-confidence, rashness, hardihood, precipitancy, recklessness, hastiness, precipitation, venturesomeness care, caution, circumspection, cowardice, hesitation, timidity, wariness
term article, denomination, member, phrase, condition, expression, name, word
terse brief, concise, neat, short, compact, condensed, pithy, succinct, compendious, laconic, sententious diffuse, lengthy, long, prolix, tedious, verbose, wordy
testimony affidavit, attestation, deposition, proof, affirmation, certification, evidence, witness
therefore accordingly, consequently, then, whence, because, hence, thence, wherefore
throng concourse, crowd, host, jam, mass, multitude, press
time age, duration, epoch, period, sequence, term, date, eon, era, season, succession, while
tip cant, dip, incline, list, slope, careen, heel over, lean, slant, tilt
tire exhaust, fatigue, harass, jade, wear out, weary, fag invigorate, recreate, refresh, relax, relieve, repose, rest, restore
tool apparatus, implement, machine, utensil, appliance, instrument, mechanism, weapon
topic division, issue, motion, proposition, subject, head, matter, point, question, theme
trace footmark, impression, remains, token, trail, footprint, mark, remnant, track, vestige, footstep, memorial, sign
transact accomplish, carry on, do, perform, act, conduct, negotiate, treat
transaction act, action, affair, business, deed, doing, proceeding
transcendental a priori, intuitive, original, primordial, transcendent
transient brief, fleeting, fugitive, short, ephemeral, flitting, momentary, temporary, evanescent, flying, passing, transitory abiding, eternal, immortal, lasting, perpetual, undying, enduring, everlasting, imperishable, permanent, persistent, unfading
union coalition, conjunction, juncture, unification, combination, junction, oneness, unity analysis, decomposition, disjunction, disunion, divorce, separation, contrariety, disconnection, dissociation, division, schism, severance
usual accustomed, everyday, general, ordinary, public, common, familiar, habitual, prevailing, regular, customary, frequent, normal, prevalent, wonted exceptional, infrequent, rare, strange, unparalleled, extraordinary, out-of-the-way, singular, uncommon, unusual
utility advantage, expediency, serviceableness, avail, profit, use, benefit, service, usefulness disadvantage, futility, inadequacy, inutility, uselessness, folly, impolicy, inexpediency, unprofitableness, worthlessness
vacant blank, leisure, unfilled, untenanted, void, empty, unemployed, unoccupied, vacuous, waste brimful, busy, filled, inhabited, overflowing, brimmed, crammed, full, jammed, packed, brimming, crowded, gorged, occupied, replete
vain abortive, futile, shadowy, unsatisfying, baseless, idle, trifling, unserviceable, bootless, inconstant, trivial, unsubstantial, deceitful, ineffectual, unavailing, useless, delusive, nugatory, unimportant, vapid, empty, null, unprofitable, visionary, fruitless, profitless, unreal, worthless adequate, effective, powerful, solid, useful, advantageous, efficient, profitable, sound, valid, beneficial, expedient, real, substantial, valuable, competent, potent, serviceable, sufficient, worthy
venal hireling, mercenary, purchasable, salable disinterested, honest, incorruptible, public-spirited, unpurchasable, generous, honorable, patriotic
venerate adore, honor, respect, revere, reverence contemn, detest, dishonor, scoff at, slight, despise, disdain, disregard, scorn, spurn
veneration adoration, awe, dread, reverence contempt, disdain, dishonor, disregard, scorn
venial excusable, pardonable, slight, trivial inexcusable, inexpiable, mortal, unpardonable, unjustifiable
veracity candor, honesty, reality, truthfulness, frankness, ingenuousness, truth, verity deceit, duplicity, falsehood, fiction, lie, deception, error, falseness, guile, mendacity, delusion, fabrication, falsity, imposture, untruth
verbal literal, oral, vocal
victory achievement, conquest, success, triumph, advantage, mastery, supremacy defeat, disappointment, failure, miscarriage, retreat, destruction, disaster, frustration, overthrow, rout
vigilant alert, cautious, on the lookout, wary, awake, circumspect, sleepless, watchful, careful, on the alert, wakeful, wide-awake careless, heedless, inconsiderate, oblivious, drowsy, inattentive, neglectful, thoughtless, dull, incautious, negligent, unwary
virtue chastity, honesty, probity, truth, duty, honor, purity, uprightness, excellence, integrity, rectitude, virtuousness, faithfulness, justice, righteousness, worth, goodness, morality, rightness, worthiness evil, vice, viciousness, wickedness, wrong
wander deviate, diverge, go astray, range, rove, swerve, digress, err, ramble, roam, stray, veer
way alley, course, lane, path, route, avenue, driveway, pass, pathway, street, bridle-path, highroad, passage, road, thoroughfare, channel, highway, passageway, roadway, track
wisdom attainment, insight, prudence, depth, judgment, reason, discernment, judiciousness, reasonableness, discretion, knowledge, sagacity, enlightenment, learning, sense, erudition, prescience, skill, foresight, profundity, understanding, information absurdity, folly, imbecility, miscalculation, senselessness, error, foolishness, imprudence, misjudgment, silliness, fatuity, idiocy, indiscretion, nonsense, stupidity
wit banter, fun, joke, waggery, burlesque, humor, playfulness, waggishness, drollery, jest, pleasantry, witticism, facetiousness, jocularity, raillery dulness, seriousness, sobriety, solemnity, stolidity, stupidity, gravity
work achievement, doing, labor, product, action, drudgery, occupation, production, business, employment, performance, toil, deed, exertion ease, idleness, leisure, recreation, relaxation, repose, rest, vacation
yet besides, further, hitherto, now, still, thus far
youthful adolescent, callow, childlike, immature, puerile, boyish, childish, girlish, juvenile, young
Can't render this file because it contains an unexpected character in line 70 and column 165.

View File

@ -0,0 +1,376 @@
"Jvgu guvrirf V pbafbeg, Jvgu gur Ivyrfg, va fubeg, V'z dhvgr ng rnfr va qrcenivgl, Lrg nyy qvivarf hfr zr, Naq fninagf pna'g ybfr zr, Sbe V nz gur pragre bs tenivgl.",I
"V zbir jvgubhg jvatf, Orgjrra fvyxra fgevat, V yrnir nf lbh svaq, Zl fhofgnapr oruvaq.",Fcvqre
"Jung syvrf sberire, Erfgf arire?",Jvaq
"V nccrne va gur zbeavat. Ohg nz nyjnlf gurer. Lbh pna arire frr zr. Gubhtu V nz rireljurer. Ol avtug V nz tbar, gubhtu V fbzrgvzrf arire jnf. Abguvat pna qrsrng zr. Ohg V nz rnfvyl tbar.",Fhayvtug
"V penjy ba gur rnegu. Naq evfr ba n cvyyne.",Funqbj
"Gurl ner znal naq bar, gurl jnir naq gurl qehz, Hfrq gb pbire n fgngr, gurl tb jvgu lbh rireljurer.",Unaqf
"Jung zhfg or va gur bira lrg pna abg or onxrq? Tebjf va gur urng lrg fuhaf gur yvtug bs qnl? Jung fvaxf va jngre ohg evfrf jvgu nve? Ybbxf yvxr fxva ohg vf svar nf unve?",Lrnfg
"V unir ubyrf ba gur gbc naq obggbz. V unir ubyrf ba zl yrsg naq ba zl evtug. Naq V unir ubyrf va gur zvqqyr, Lrg V fgvyy ubyq jngre.",Fcbatr
"Jung pna or fjnyybjrq, Ohg pna nyfb fjnyybj lbh?",Cevqr
"Lbh trg znal bs zr, ohg arire rabhtu. Nsgre gur ynfg bar, lbhe yvsr fbba jvyy fahss. Lbh znl unir bar bs zr ohg bar qnl n lrne, Jura gur ynfg bar vf tbar, lbhe yvsr qvfnccrnef.",Oveguqnl
"V eha nebhaq gur pvgl, ohg V arire zbir.",Jnyy
"Nf n jubyr, V nz obgu fnsr naq frpher. Orurnq zr, V orpbzr n cynpr bs zrrgvat. Orurnq zr ntnva, V nz gur cnegare bs ernql. Erfgber zr, V orpbzr gur qbznva bs ornfgf.",Fgnoyr
"Gjb ubefrf, fjvsgrfg geniryvat, unearffrq va n cnve, naq tenmvat rire va cynprf. Qvfgnag sebz gurz.",Rlrf
"Ng gur fbhaq bs zr, zra znl qernz. Be fgnzc gurve srrg. Ng gur fbhaq bs zr, jbzra znl ynhtu. Be fbzrgvzrf jrrc.",Zhfvp
"Gb haeniry zr lbh arrq n fvzcyr xrl, ab xrl gung jnf znqr ol ybpxfzvgu'f unaq. Ohg n xrl gung bayl V jvyy haqrefgnaq.",Evqqyr
"Ybat naq guvax, erq jvguva, jvgu n anvy ng gur raq.",Svatre
"V'z fbzrgvzrf juvgr naq nyjnlf jebat. V pna oernx n urneg naq uheg gur fgebat. V pna ohvyq ybir be grne vg qbja. V pna znxr n fzvyr be oevat n sebja.",Yvr
"Lbh pna ghzoyr va vg, ebyy va vg, ohea vg, navzny rng vg. Hfrq gb pbire sybbef, fgvyy hfrq orlbaq fgnyy qbbef. Serfuraf jungrire vg vf cynprq ba. Nofbeof jungrire vf cbherq vagb vg.",Unl
"V pbzr va jvagre. V pnaabg frr, urne, be srry. V pna'g rng, Ohg lbh pna rng cnegf bs zr.",Fabjzna
"Fbzrgvzrf V nz ybhq. Naq ivrjrq jvgu qvfgnfgr. Cbxr bhg zl 'rlr', gura V'z ba gur sebag bs lbhe snpr.",Abvfr
"Jung vf vg gung unf sbhe yrtf, bar urnq, naq n sbbg?",Orq
"Jung znxrf n ybhq abvfr jura punatvat vgf wnpxrg. Orpbzrf ynetre ohg jrvtuf yrff?",Cbcpbea
"V nz nyjnlf uhatel, V zhfg nyjnlf or srq. Gur svatre V yvpx jvyy fbba ghea erq.",Sver
"Fbzrguvat jubyyl haerny, lrg frrzf erny gb V. Guvax zl sevraq, gryy zr jurer qbrf vg yvr?",Zvaq
"Ab znggre ubj yvggyr be ubj zhpu lbh hfr zr, lbh punatr zr rirel zbagu.",Pnyraqne
"Jung pna ohea gur rlrf, fgvat gur zbhgu, lrg or pbafhzrq?",Fnyg
"Jung na svyy n ebbz ohg gnxrf hc ab fcnpr?",Yvtug
"Vg bpphef bapr va rirel zvahgr. Gjvpr va rirel zbzrag naq lrg arire va bar uhaqerq gubhfnaq lrnef.",Z
"Jvgu cbvagrq snatf vg fvgf va jnvg. Jvgu cvrepvat sbepr vg qbyrf bhg sngr, bire oybbqyrff ivpgvzf cebpynvzvat vgf zvtug. Rgreanyyl wbvavat va n fvatyr ovgr.",Fgncyre
"Vg ubyqf zbfg xabjyrqtr gung unf rire orra fnvq. Ohg vf abg gur oenva, vf abg gur urnq. Gb srnguref naq gurve znfgref, vg'f obgu onar naq obba. Bar rzcgl, naq bar shyy.",Cncre
"Hcba zr lbh pna gernq, gubhtu fbsgyl haqre pbire. Naq V jvyy gnxr lbh cynprf, gung lbh unir lrg gb qvfpbire. V'z uvtu, naq V'z ybj, gubhtu syng va gur zvqqyr. Naq gubhtu n wbl gb gur puvyqera, nqhygf guvax bs zr yvggyr.",Fgnvef
"N zvyr sebz raq gb raq, lrg nf pybfr gb nf n sevraq. N cerpvbhf pbzzbqvgl, serryl tvira. Frra ba gur qrnq naq ba gur yvivat. Sbhaq ba gur evpu, cbbe, fubeg naq gnyy. Ohg funerq nzbat puvyqera zbfg bs nyy.",Fzvyr
"V unir n uhaqerq yrtf, ohg pnaabg fgnaq. V unir n ybat arpx, ohg ab urnq. V pnaabg frr. V'z arng naq gvql nf pna or.",Oebbz
"Syng nf n yrns, ebhaq nf n evat. Unf gjb rlrf, pna'g frr n guvat.",Ohggba
"V qba'g guvax be rng be fyhzore. Be zbir nebhaq be srne guhaqre. Whfg yvxr lbh V ybbx gur fnzr ohg V pna'g unez lbh be or lbhe onar.",Qbyy
"Va zneoyr unyyf nf juvgr nf zvyx, yvarq jvgu n fxva nf fbsg nf fvyx. Jvguva n sbhagnva pelfgny-pyrne. N tbyqra nccyr qbgu nccrne. Ab qbbef gurer ner gb guvf fgebatubyq, lrg guvrirf oernx va naq fgrny gur tbyq.",Rtt
"Jung vf vg gung lbh zhfg tvir orsber lbh pna xrrc vg.",Jbeq
"V qvt bhg gval pnirf naq fgber tbyq naq fvyire va gurz. V nyfb ohvyq oevqtrf bs fvyire naq znxr pebjaf bs tbyq. Gurl ner gur fznyyrfg lbh pbhyq vzntvar. Fbbare be yngre rirelobql arrqf zl uryc. Lrg znal crbcyr ner nsenvq gb yrg zr uryc gurz.",Qragvfg
"Jung vf ybat naq fyvz, jbexf va yvtug. Unf ohg bar rlr, naq na njshy ovgr?",Arrqyr
"Jung yvrf va n ghaary bs qnexarff. Gung pna bayl nggnpx jura chyyrq onpx?",Ohyyrg
"Jung unf fvk snprf naq gjragl-bar rlrf?",Qvr
"Hagvy V nz zrnfherq. V nz abg xabja, lrg ubj lbh zvff zr jura V unir sybja.",Gvzr
"Guerr yvirf unir V. Tragyr rabhtu gb fbbgur gur fxva. Yvtug rabhtu gb pnerff gur fxl. Uneq rabhtu gb penpx ebpxf.",Jngre
"V jrne n erq ebor, jvgu fgnss va unaq, naq n fgbar va zl guebng.",Pureel
"N jneevbe nzbatfg gur sybjref, ur ornef n guehfgvat fjbeq. Ur hfrf vg jurarire ur zhfg, gb qrsraq uvf tbyqra ubneq.",Orr
"V uvqr ohg zl urnq vf bhgfvqr.",Anvy
"N ubhfr shyy, n lneq shyy, n puvzarl shyy, ab bar pna trg n fcbbashy.",Fzbxr
"Lbh pna fcva, jurry naq gjvfg. Ohg guvf guvat pna ghea jvgubhg zbivat.",Zvyx
"Unyb bs jngre, gbathr bs jbbq. Fxva bs fgbar, ybat V'ir fgbbq. Zl svatref fubeg ernpu gb gur fxl. Vafvqr zl urneg zra yvir naq qvr.",Pnfgyr
"Jura gurl ner pnhtug, gurl ner guebja njnl. Jura gurl rfpncr, lbh vgpu nyy qnl.",Syrnf
"Jung qbrf zna ybir zber guna yvsr, srne zber guna qrngu be zbegny fgevsr. Jung gur cbbe unir, gur evpu erdhver, naq jung pbagragrq zra qrfver. Jung gur zvfre fcraqf, naq gur fcraqguevsg fnirf. Naq nyy zra pneel gb gurve tenirf.",Abguvat
"Va jr tb, bhg jr tb. Nyy nebhaq naq va n ebj. Nyjnlf, nyjnlf fgrnql sybj. Jura jr'yy fgbc, lbh'yy arire xabja. Va jr tb, bhg jr tb.",Gvqrf
"N pybhq jnf zl zbgure, gur jvaq vf zl sngure. Zl fba vf gur pbby fgernz, naq zl qnhtugre vf gur sehvg bs gur ynaq. N envaobj vf zl orq, gur rnegu zl svany erfgvat cynpr. Naq V'z gur gbezrag bs zna.",Enva
"Obea bs rnegu, ohg jvgu abar bs vgf fgeratgu. Zbyqrq ol synzr, ohg jvgu abar bs vgf cbjre. Funcrq",Tynff
"Erzbir gur bhgfvqr. Pbbx gur vafvqr. Rng gur bhgfvqr. Guebj njnl gur vafvqr.",Pbea
"Guvf vf va n ernyz bs gehr naq va n ernyz snyfr, ohg lbh rkcrevrapr zr nf lbh ghea naq gbff.",Qernz
"Gurer vf na napvrag vairagvba. Fgvyy hfrq va fbzr cnegf bs gur jbeyq gbqnl. Gung nyybjf crbcyr gb frr guebhtu jnyyf.",Jvaqbj
"Fbzr yvir va zr, fbzr yvir ba. Naq fbzr funir zr gb fgevqr hcba. V eneryl yrnir zl angvir ynaq. Hagvy zl qrngu V nyjnlf fgnaq. Uvtu naq ybj V znl or sbhaq. Obgu nobir naq orybj tebhaq.",Gerr
"Zrgny be obar V znl or, znal grrgu V unir naq nyjnlf onerq. Lrg zl ovgr unezf ab bar. Naq ynqvrf qryvtug va zl gbhpu.",Pbzo
"V nz n sver'f orfg sevraq. Jura sng, zl obql svyyf jvgu jvaq. Jura chfurq gb guva, guebhtu zl abfr V oybj. Gura lbh pna jngpu gur rzoref tybj.",Oryybjf
"Rirel qnja ortvaf jvgu zr. Ng qhfx V'yy or gur svefg lbh frr, naq qnloernx pbhyqa'g pbzr jvgubhg. Jung zvqqnl pragref nyy nobhg. Qnvfrf tebj sebz zr, V'z gbyq. Naq jura V pbzr, V raq nyy pbqr, ohg va gur fha V jba'g or sbhaq. Lrg fgvyy, rnpu qnl V'yy or nebhaq.",Q
"Lbh urneg vg fcrnx, sbe vg unf n uneq gbathr. Ohg vg pnaabg oerngur, sbe vg unf abg n yhat.",Oryy
"V phg guebhtu rivy yvxr n qbhoyr rqtrq fjbeq, naq punbf syrrf ng zl nccebnpu. Onynapr V fvatyr-unaqrqyl hcenvfr, guebhtu onggyrf sbhtug jvgu urneg naq zvaq, vafgrnq bs jvgu zl tnmr.",Whfgvpr
"Gur rvtug bs hf zbir sbegu naq onpx. Gb cebgrpg bhe xvat sebz gur sbrf nggnpx.",Cnjaf
"Ur unf bar naq n crefba unf gjb. N pvgvmra unf guerr. Naq n uhzna orvat unf sbhe. N crefbanyvgl unf svir. Naq na vaunovgnag bs rnegu unf fvk.",Flyynoyr
"Vs lbh oernx zr, V qb abg fgbc jbexvat. Vs lbh gbhpu zr, V znl or fanerq. Vs lbh ybfr zr, abguvat jvyy znggre.",Urneg
"Jung'f va gur zvqqyr bs abjurer?",U
"Jung sbepr naq fgeratgu pnaabg trg guebhtu. V, jvgu n tragyr gbhpu, pna qb. Znal va gur fgerrg jbhyq fgnaq. Jrer V abg n sevraq ng unaq.",Xrl
"Bsgra uryq ohg arire gbhpurq. Nyjnlf jrg ohg arire ehfgf. Bsgra ovgf ohg fryqbz ovg. Gb hfr vg jryy lbh zhfg unir jvg.",Gbathr
"Nf ebhaq nf na nccyr. Nf qrrc nf n phc. Nyy gur xvat'f ubefrf pna'g chyy vg hc.",Jryy
"Ur fgnaqf orfvqr gur ebnq. Va n checyr pnc ng gnggrerq terra pybnx. Gubfr jub gbhpu uvz, phefr uvz.",Guvfgyr
"Cbjre rabhtu gb fznfu fuvcf naq pehfu ebbsf. Lrg vg fgvyy zhfg srne gur fha.",Vpr
"Jung fheebhaqf gur jbeyq, lrg qjryyf jvguva n guvzoyr?",Fcnpr
"V pnaabg or bgure guna jung V nz, hagvy gur zna jub znqr zr qvrf. Cbjre naq tybel jvyy snyy gb zr svanyyl. Bayl jura ur ynfg pybfrf uvf rlrf.",Cevapr
"Jung vf vg gung znxrf grnef jvgubhg fbeebj. Naq gnxrf vgf wbhearl gb urnira?",Fzbxr
"Vafvqr n terng oyhr pnfgyr yvirf n ful lbhat znvq. Fur oyhfurf va gur zbeavat naq pbzrf abg bhg ng avtug.",Fha
"Guvf guvat ehaf ohg pnaabg jnyx, fbzrgvzrf fvatf ohg arire gnyxf. Ynpxf nezf, unf unaqf; ynpxf n urnq ohg unf n snpr.",Pybpx
"N jbeq V xabj, fvk yrggref vg pbagnvaf. Fhogenpg whfg bar naq gjryir erznvaf.",Qbmraf
"V tb va uneq naq qel. V pbzr bhg fbsg naq fgvpxl. Lbh pna oybj zr.",Thz
"V nz gur lryybj urz bs gur frn'f oyhr fxveg.",Ornpu
"N fxva unir V, zber rlrf guna bar. V pna or irel avpr jura V nz qbar.",Cbgngb
"V unir sbhe yrtf ohg ab gnvy. Hfhnyyl V nz urneq bayl ng avtug.",Sebt
"N gval ornq, yvxr sentvyr tynff, fgehat nybat n pbeq bs tenff.",Qrj
"Oernx vg naq vg vf orggre, vzzrqvngryl frg naq uneqre gb oernx ntnva.",Erpbeq
"Rnpu zbeavat V nccrne gb yvr ng lbhe srrg, nyy qnl V sbyybj ab znggre ubj snfg lbh eha. Lrg V arneyl crevfu va gur zvqqnl fha.",Funqbj
"Jung qb lbh guebj bhg gb hfr naq gnxr va jura lbh'er qbar?",Napube
"Jung vf vg juvpu ohvyqf guvatf hc? Ynlf zbhagnvaf ybj? Qevrf hc ynxrf, naq znxrf guvatf tebj? Pnerf abg n juvz nobhg lbhe cnffvat? Naq vf yvxr srj bgure guvatf, orpnhfr vg vf rireynfgvat?",Gvzr
"V nz gur sbhagnva sebz juvpu ab bar pna qevax. Sbe znal V nz pbafvqrerq n arprffnel yvax. Yvxr tbyq gb nyy V nz fbhtug sbe, ohg zl pbagvahrq qrngu oevatf jrnygu sbe nyy gb jnag zber.",Bvy
"Fyrrcvat qhevat gur qnl, V uvqr njnl. Jngpushy guebhtu gur avtug, V bcra ng qnja'f yvtug. Ohg bayl sbe gur oevrsrfg gvzr, qb V fuvar. Naq gura V uvqr njnl. Naq fyrrc guebhtu gur qnl.",Fhaevfr
"N frrq nz V, guerr yrggref znxr zl anzr. Gnxr njnl gjb naq V fgvyy fbhaq gur fnzr.",Crn
"Va gur zvqqyr bs avtug, V fheebhaq gur tbat. Va gur zvqqyr bs fvtug, V raq gur fbat.",T
"Ybbx vagb zl snpr naq V'z rirelobql. Fpengpu zl onpx naq V'z abobql.",Zveebe
"Gjb oebguref jr ner, terng oheqraf jr orne. Nyy qnl jr ner ovggreyl cerffrq. Lrg guvf V jvyy fnl, jr ner shyy nyy gur qnl, naq rzcgl jura tb gb erfg.",Obbgf
"Gurl pna or uneoberq, ohg srj ubyq jngre. Lbh pna ahefr gurz, ohg bayl ol ubyqvat gurz ntnvafg fbzrbar ryfr. Lbh pna pneel gurz, ohg abg jvgu lbhe nezf. Lbh pna ohel gurz, ohg abg va gur rnegu.",Tehqtr
"Jung vf vg gung jnf tvira gb lbh, orybatf bayl gb lbh. Naq lrg lbhe sevraqf hfr vg zber guna lbh qb?",Anzr
"Ol Zbba be ol Fha, V funyy or sbhaq. Lrg V nz haqbar, vs gurer'f ab yvtug nebhaq.",Funqbj
"Jung qb lbh hfr gb ubr n ebj, fynl n sbr, naq jevat jvgu jbr?",Unaqf
"Jr geniry zhpu, lrg cevfbaref ner, naq pybfr pbasvarq gb obbg. Lrg jvgu nal ubefr, jr jvyy xrrc gur cnpr, naq jvyy nyjnlf tb ba sbbg.",Fchef
"Jvgubhg n oevqyr, be n fnqqyr, npebff n guvat V evqr n-fgenqqyr. Naq gubfr V evqr, ol uryc bs zr, gubhtu nyzbfg oyvaq, ner znqr gb frr.",Tynffrf
"V syl guebhtu gur nve ba fznyy srngurerq jvatf, frrxvat bhg yvsr naq qrfgeblvat nyy guvatf.",Neebj
"V nz gur erq gbathr bs gur rnegu, gung ohevrf pvgvrf.",Ynin
"V ybbx ng lbh, lbh ybbx ng zr, V envfr zl evtug, lbh envfr lbhe yrsg.",Zveebe
"Jung vf gur guvat juvpu, bapr cbherq bhg, pnaabg or tngurerq ntnva?",Enva
"Vg vf n cneg bs hf, naq gura ercynprq. Vg rfpncrf bhg obqvrf, gb n orggre cynpr. Gur jbeyq orpbzrf vgf fvmrnoyr ubzr. Vgf cnffvbaf haerfgenvag, gur cynarg vg ebnzf.",Jngre
"Jung jbeq fgnegf jvgu 'R', raqf jvgu 'R', ohg bayl unf bar yrggre? Vg vf abg gur yrggre 'R'.",Rairybcr
"N ubyr va n cbyr, gubhtu V svyy n ubyr va juvgr. V'z hfrq zber ol gur qnl, naq yrff ol gur avtug.",Rlr
"V syl, lrg V unir ab jvatf. V pel, lrg V unir ab rlrf. Qnexarff sbyybjf zr. Ybjre yvtug V arire frr.",Pybhq
"V'z shyy bs ubyrf, lrg V'z shyy bs jngre.",Fcbatr
"Ybat naq fyvaxl yvxr n gebhg, arire fvatf gvyy vg'f thgf pbzr bhg.",Tha
"Jung navzny xrrcf gur orfg gvzr?",Jngpuqbt
"Jung xvaq bs ebbz unf ab jvaqbjf be qbbef?",Zhfuebbz
"V unir yrtf ohg jnyx abg, n fgebat onpx ohg jbex abg. Gjb tbbq nezf ohg ernpu abg. N frng ohg fvg naq gneel abg.",Punve
"Vg'f va lbhe unaq gubhtu lbh pna abg srry vg. Bayl lbh naq gvzr pna erirny vg.",Sngr
"Abg obea, ohg sebz n Zbgure'f obql qenja. V unat hagvy unys bs zr vf tbar. V fyrrc va n pnir hagvy V tebj byq. Gura inyhrq sbe zl uneqrarq tbyq.",Purrfr
"V nz gur bhgfgergpurq svatref gung frvmr naq ubyq gur jvaq. Jvfqbz sybjf sebz zr va bgure unaqf. Hcba zr ner fjrrg qernzf qernzg, zl zrerfg gbhpu oevatf ynhtugre.",Srngure
"Unaqf fur unf ohg qbrf abg ubyq. Grrgu fur unf ohg qbrf abg ovgr. Srrg fur unf ohg gurl ner pbyq. Rlrf fur unf ohg jvgubhg fvtug.",Qbyy
"Bayl gjb onpxobarf naq gubhfnaqf bs evof.",Envyebnq
"Uneq veba ba ubefr. Pbj'f uvqr ba zna.",Fubr
"Jung jbeq vf gur fnzr jevggra sbejneq, onpxjneq naq hcfvqr qbja?",Abba
"V pnaabg or sryg, frra be gbhpurq. Lrg V pna or sbhaq va rirelobql. Zl rkvfgrapr vf nyjnlf va qrongr. Lrg V unir zl bja fglyr bs zhfvp.",Fbhy
"V nz frra va gur jngre. Vs frra va gur fxl, V nz va gur envaobj, n wnl'f srngure, naq yncvf ynmhyv.",Oyhr
"Lbh hfr vg orgjrra lbhe urnq naq lbhe gbrf, gur zber vg jbexf gur guvaare vg tebjf.",Fbnc
"Sngureyrff naq zbgureyrff. Obea jvgubhg fva, ebnerq jura vg pnzr vagb gur jbeyq. Naq arire fcbxr ntnva.",Guhaqre
"Jurer pna lbh svaq ebnqf jvgubhg pnef, sberfgf jvgubhg gerrf naq pvgvrf jvgubhg ubhfrf?",Znc
"N yrngurel fanxr, jvgu n fgvatvat ovgr. V'yy fgnl pbvyrq hc, hayrff V zhfg svtug.",Juvc
"Gnxr bar bhg naq fpengpu zl urnq, V nz abj oynpx ohg bapr jnf erq.",Zngpu
"Zbhagnvaf jvyy pehzoyr naq grzcyrf jvyy snyy. Naq ab zna pna fheivir vgf raqyrff pnyy.",Gvzr
"Jung unf jvatf, ohg pna abg syl. Vf rapybfrq, ohg pna bhgfvqr nyfb yvr. Pna bcra vgfrys hc, be pybfr vgfrys njnl. Vf gur cynpr bs xvatf naq dhrraf naq qbttrery bs rirel zrnaf. Jung vf vg hcba juvpu V fgnaq? Juvpu pna yrnq hf gb qvssrerag ynaqf.",Fgntr
"V'z gur fbhepr bs nyy rzbgvba, ohg V'z pntrq va n juvgr cevfba.",Urneg
"V nz gur gbby, sbe vafcvevat znal. Ohl zr va gur fgber, sbe abg zhpu zber guna n craal. Qba'g birehfr zr, be zl hfrshyarff jvyy tb.",Cra
"Jung tbrf guebhtu n qbbe ohg arire tbrf va. Naq arire pbzrf bhg?",Xrlubyr
"Jung tbrf hc jura gur enva pbzrf qbja?",Hzoeryyn
"V bpphe gjvpr va rgreavgl. Naq V'z nyjnlf jvguva fvtug.",G
"Gjvtf naq fcurerf naq cbyrf naq cyngrf. Wbva naq ovaq gb ernfba znxr.",Fxryrgba
"Gur fha onxrf gurz, gur unaq oernxf gurz, gur sbbg gernqf ba gurz, naq gur zbhgu gnfgrf gurz.",Tencrf
"V unir znal srnguref gb uryc zr syl. V unir n obql naq urnq, ohg V'z abg nyvir. Vg vf lbhe fgeratgu juvpu qrgrezvarf ubj sne V tb. Lbh pna ubyq zr va lbhe unaq, ohg V'z arire guebja.",Neebj
"Jung'f oynpx jura lbh trg vg, erq jura lbh hfr vg, naq juvgr jura lbh'er nyy guebhtu jvgu vg?",Punepbny
"Jung unf sbhe yrtf va gur zbeavat, gjb yrtf va gur nsgreabba, naq guerr yrtf va gur riravat?",Zna
"Gnxr bss zl fxva, V jba'g pel, ohg lbh jvyy.",Bavba
"Ubyq gur gnvy, juvyr V svfu sbe lbh.",Arg
"V nz fb fvzcyr gung V pna bayl cbvag. Lrg V thvqr zra nyy bire gur jbeyq.",Pbzcnff
"Veba ebbs, tynff jnyyf, oheaf naq oheaf naq arire snyyf.",Ynagrea
"Yngr nsgreabbaf V bsgra ongur. V'yy fbnx va jngre cvcvat ubg. Zl rffrapr tbrf guebhtu. Zl frr guebhtu pybgurf. Hfrq hc nz V - V'ir tbar gb cbg.",Grnont
"Jung pna'g lbh frr, urne be srry, hagvy vgf gbb yngr. Jung funqbjf ybir, naq fubcxrrcref ungr?",Guvrs
"Jung pna oevat onpx gur qrnq. Znxr hf pel, znxr hf ynhtu, znxr hf lbhat. Obea va na vafgnag lrg ynfgf n yvsr gvzr?",Zrzbel
"V unir n arpx ohg ab urnq. V unir n obql ohg ab nez. V unir n obggbz ohg ab yrt.",Obggyr
"N gubhfnaq pbyberq sbyqf fgergpu gbjneq gur fxl. Ngbc n graqre fgenaq, evfvat sebz gur ynaq, hagvy xvyyrq ol znvqra'f unaq. Creuncf n gbxra bs ybir, creuncf gb fnl tbbqolr.",Sybjre
"Tbyq va n yrngure ont, fjvatvat ba n gerr, zbarl nsgre ubarl va vgf gvzr. Vyyf bs n fpheil perj pherq ol gur frn, ernfba va vgf frnfba ohg ab eulzr.",Benatr
"N fybj, fbyrza fdhner-qnapr bs jneevbef srvagvat. Bar ol bar gurl snyy, jneevbef snvagvat, guvegl-gjb ba fvkgl-sbhe.",Purff
"Ur unf zneevrq znal jbzra ohg unf arire zneevrq.",Cevrfg
"Va lbhe sver lbh urne zr fpernz, pernxvat naq juvavat, lrg V nz qrnq orsber lbh ynl zr va lbhe urnegu.",Ybt
"V jrnxra nyy zra sbe ubhef rnpu qnl. V fubj lbh fgenatr ivfvbaf juvyr lbh ner njnl. V gnxr lbh ol avtug, ol qnl gnxr lbh onpx. Abar fhssre gb unir zr, ohg qb sebz zl ynpx.",Fyrrc
"V fnj n fgenatr perngher. Ybat, uneq, naq fgenvtug, guehfgvat vagb n ebhaq, qnex bcravat. Cercnevat gb qvfpunetr vgf ybnq bs yvirf. Chssvat naq fdhrnyvat abvfrf nppbzcnavrq vg, gura n svany fperrpu nf vg fybjrq naq fgbccrq.",Genva
"Ynetr nf n zbhagnva, fznyy nf n crn, raqyrffyl fjvzzvat va n jngreyrff frn.",Nfgrebvq
"V qb abg oerngur, ohg V eha naq whzc. V qb abg rng, ohg V fjvz naq fgergpu. V qb abg qevax, ohg V fyrrc naq fgnaq. V qb abg guvax, ohg V tebj naq cynl. V qb abg frr, ohg lbh frr zr rirelqnl.",Yrt
"Jura yvdhvq fcynfurf zr, abar frrcf guebhtu. Jura V nz zbirq n ybg, yvdhvq V fcrj. Jura V nz uvg, pbybe V punatr. Naq pbybe, V pbzr va dhvgr n enatr. Jung V pbire vf irel pbzcyrk, naq V nz irel rnfl gb syrk.",Fxva
"Tvir vg sbbq naq vg jvyy yvir, tvir vg jngre naq vg jvyy qvr.",Sver
"N ahg penpxre hc va n gerr.",Fdhveery
"Jung unccraf rirel frpbaq, zvahgr, zbagu, naq praghel. Ohg abg rirel ubhe, jrrx, lrne, be qrpnqr?",A
"Vg unf ab gbc be obggbz, ohg vg pna ubyq syrfu, obarf, naq oybbq nyy ng gur fnzr gvzr.",Evat
"V nz serr sbe gur gnxvat. Guebhtu nyy bs lbhe yvsr, gubhtu tvira ohg bapr ng ovegu. V nz yrff guna abguvat va jrvtug, ohg jvyy sryy gur fgebatrfg bs lbh vs uryq.",Oerngu
"Zl svefg vf va oybbq naq nyfb va onggyr. Zl frpbaq vf va npbea, bnx, naq nccyr. Zl guveq naq sbhegu ner obgu gur fnzr. Va gur pragre bs fbeebj naq gjvpr va ersenva. Zl svsgu fgnegf rgreavgl raqvat urer. Zl ynfg vf gur svefg bs ynfg, Bu Qrne.",Oneery
"Jura V'z zrgny be jbbq, V uryc lbh trg ubzr. Jura V'z syrfu naq V'z oybbq. Va gur qnexarff V ebnz.",Ong
"V znepu orsber nezvrf, n gubhfnaq fnyhgr zr. Zl snyy pna oevat ivpgbel, ohg ab bar jbhyq fubbg zr. Gur jvaq vf zl ybire, bar-yrttrq nz V. Anzr zr naq frr zr ng ubzr va gur fxl.",Synt
"Gbby bs guvrs, gbl bs dhrra. Nyjnlf hfrq gb or hafrra. Fvta bs wbl, fvta bs fbeebj. Tvivat nyy yvxrarff obeebjrq.",Znfx
"Jung svir-yrggre jbeq orpbzrf fubegre jura lbh nqq gjb zber yrggref?",Fubeg
"Jung vf cebabhaprq yvxr bar yrggre, jevggra jvgu guerr yrggref. Naq orybatf gb nyy navznyf?",Rlr
"Jung vf vg gung tvira bar, lbh'yy unir rvgure gjb be abar?",Pubvpr
"Vg vf terngre guna Tbq naq zber rivy guna gur qrivy. Gur cbbe unir vg, gur evpu arrq vg, naq vs lbh rng vg lbh'yy qvr.",Abguvat
"Jung trgf ovttre gur zber lbh gnxr njnl sebz vg?",Ubyr
"Gur zber bs vg gurer vf, gur yrff lbh frr.",Qnexarff
"Gb pebff gur jngre V'z gur jnl, sbe jngre V'z nobir. V gbhpu vg abg naq, gehgu gb fnl, V arvgure fjvz abe zbir.",Oevqtr
"Nf ornhgvshy nf gur frggvat fha, nf qryvpngr nf gur zbeavat qrj. Na natry'f qhfgvat sebz gur fgnef. Gung pna ghea gur Rnegu vagb n sebfgrq zbba.",Fabj
"Jura frg ybbfr V syl njnl. Arire fb phefrq nf jura V tb nfgenl.",Sneg
"Ubj sne jvyy n oyvaq qbt jnyx vagb n sberfg?",Unysjnl
"Zl svefg vf va jvryq, frire obarf naq zneebj. Zl frpbaq vf va oynqr, sbetrq va pbyq fgrry. Zl guveq vf na neonyrfg, naq nyfb va neebjf. Zl sbhegu vf va cbjre, cyhatrq guebhtu n fuvryq. Zl svsgu vf va ubabe, naq nyfb va ibjf. Zl ynfg jvyy chg na raq gb vg nyy.",Jrncba
"Snpr jvgu n gerr, fxva yvxr gur frn. N terng ornfg V nz. Lrg irezva sevtugraf zr.",Ryrcunag
"V fyrrc ol qnl, V syl ol avtug. V unir ab srnguref gb nvq zl syvtug.",Ong
"V nz zbgure naq sngure, ohg arire ovegu be ahefr. V'z eneryl fgvyy, ohg V arire jnaqre.",Gerr
"Jung tbrf va gur jngre erq, naq pbzrf bhg oynpx?",Veba
"Tebjf sebz gur tebhaq, ohfurf naq tenff, yrnirf bs lryybj, erq naq oebja, haehyl cynagf, trg gur nkr, gevz gur urqtr onpx qbja.",Unve
"Jung pna gbhpu fbzrbar bapr naq ynfg gurz n yvsr gvzr?",Ybir
"N qentbaf gbbgu va n zbegnyf unaq, V xvyy, V znvz, V qvivqr gur ynaq.",Fjbeq
"Lbh jvyy svaq zr jvgu sbhe yrtf, ohg ab unve. Crbcyr evqr zr sbe ubhef, ohg V qba'g tb naljurer jvgubhg arrqvat gb or ghttrq. Wrexrq be ghearq ba, V nyjnlf znantr gb or ernql sbe jbex.",Qrfx
"Ab fbbare fcbxra guna oebxra.",Fvyrapr
"Gubhtu qrfreg zra bapr pnyyrq zr Tbq, gbqnl zra pnyy zr znq. Sbe V jnt zl gnvy jura V nz natel. Naq tebjy jura V nz tynq.",Png
"Na bcra raqrq oneery, vg vf funcrq yvxr n uvir. Vg vf svyyrq jvgu gur syrfu, naq gur syrfu vf nyvir.",Guvzoyr
"Jung xvaq bs crg nyjnlf fgnlf ba gur sybbe?",Pnecrg
"Jung syvrf jvgubhg jvatf? Jung cnffrf nyy guvatf? Jung zraqf nyy fbeebj? Jung oevatf gur zbeebj?",Gvzr
"Jung unf n arpx naq ab urnq, gjb nezf ohg ab unaqf?",Fuveg
"Gjb va n pbeare, bar va n ebbz, abar va n ubhfr, ohg bar va n furygre.",E
"Jung qbrf ab zna jnag, lrg ab zna jnag gb ybfr?",Jbex
"V nz gur urneg gung qbrf abg orng. Vs phg, V oyrrq jvgubhg oybbq. V pna syl, ohg unir ab jvatf. V pna sybng, ohg unir ab svaf. V pna fvat, ohg unir ab zbhgu.",Jbbq
"Jrvtug va zl oryyl, gerrf ba zl onpx, anvyf va zl evof, srrg V qb ynpx.",Obng
"Jung vf gung bire gur urnq naq haqre gur ung?",Unve
"V ovaq vg naq vg jnyxf. V ybbfr vg naq vg fgbcf.",Fnaqny
"Zl ibvpr vf graqre, zl jnvfg vf fyraqre naq V'z bsgra vaivgrq gb cynl. Lrg jurerire V tb, V zhfg gnxr zl obj be ryfr V unir abguvat gb fnl.",Ivbyva
"Ybiryl naq ebhaq, V fuvar jvgu cnyr yvtug, tebja va gur qnexarff, n ynql'f qryvtug.",Crney
"Gur fgenatrfg perngher lbh'yy rire svaq unf gjb rlrf va sebag naq n uhaqerq oruvaq.",Crnpbpx
"N yvggyr cbby jvgu gjb ynlref bs jnyy nebhaq vg. Bar juvgr naq fbsg naq gur bgure qnex naq uneq. Nzvqfg n yvtug oebja tenffl ynja jvgu na bhgyvar bs n terra tenff.",Pbpbahg
"V bcra jvqr naq gvtug V fuhg, Funec nz V naq cncre-phg svatref gbb, fb qb gnxr pner, V'z tbbq naq onq, fb orfg orjner.",Fpvffbef
"Bayl bar pbybe, ohg abg bar fvmr. Fghpx ng gur obggbz, lrg rnfvyl syvrf. Cerfrag va fha, ohg abg va enva. Qbvat ab unez, naq srryvat ab cnva.",Funqbj
"N ubhfr bs jbbq va n uvqqra cynpr. Ohvyg jvgubhg anvyf be tyhr. Uvtu nobir gur rnegura tebhaq. Vg ubyqf cnyr trzf bs oyhr.",Arfg
"Jub fcraqf gur qnl ng gur jvaqbj, tbrf gb gur gnoyr sbe zrnyf. Naq uvqrf ng avtug?",Syl
"Gur ortvaavat bs rgreavgl, gur raq bs gvzr naq fcnpr, gur ortvaavat bs rirel raq, gur raq bs rirel cynpr.",R
"Nyjnlf byq, fbzrgvzrf arj. Arire fnq, fbzrgvzrf oyhr. Arire rzcgl, fbzrgvzrf shyy. Arire chfurf, nyjnlf chyyf.",Zbba
"V ohooyr naq ynhtu naq fcvg jngre va lbhe snpr. V nz ab ynql, naq V qba'g jrne ynpr.",Sbhagnva
"Zl grrgu ner funec, zl onpx vf fgenvtug, gb phg guvatf hc vg vf zl sngr.",Fnj
"V ybir gb qnapr naq gjvfg naq cenapr. V funxr zl gnvy, nf njnl V fnvy. Jvatyrff V syl vagb gur fxl.",Xvgr
"V hfhnyyl jrne n lryybj pbng. V hfhnyyl unir n qnex urnq. V znxr znexf jurerire V tb.",Crapvy
"Zl yvsr vf bsgra n ibyhzr bs tevrs, lbhe uryc vf arrqrq gb ghea n arj yrns. Fgvss vf zl fcvar naq zl obql vf cnyr. Ohg V'z nyjnlf ernql gb gryy n gnyr.",Obbx
"V pbfg ab zbarl gb hfr, be pbafpvbhf rssbeg gb gnxr cneg bs. Naq nf sne nf lbh pna frr, gurer vf abguvat gb zr. Ohg jvgubhg zr, lbh ner qrnq.",Nve
"Fbyqvref yvar hc fcnprq jvgu cevqr. Gjb ybat ebjf yvarq fvqr ol fvqr. Bar fbyr havg pna qrpvqr, vs gur ebjf jvyy havg be qvivqr.",Mvccre
"Jung zrnfherf bhg gvzr. Hagvy va gvzr nyy vf fznfurq gb vg?",Fnaq
"V ghea nebhaq bapr. Jung vf bhg jvyy abg trg va. V ghea nebhaq ntnva. Jung vf va jvyy abg trg bhg.",Xrl
"Jub vf ur gung ehaf jvgubhg n yrt. Naq uvf ubhfr ba uvf onpx?",Fanvy
"Jura gur qnl nsgre gbzbeebj vf lrfgreqnl. Gbqnl jvyy or nf sne sebz Jrqarfqnl. Nf gbqnl jnf sebz Jrqarfqnl. Jura gur qnl orsber lrfgreqnl jnf gbzbeebj. Jung vf gur qnl nsgre guvf qnl?",Guhefqnl
"Jung unf ebbgf nf abobql frrf, vf gnyyre guna gerrf. Hc, hc vg tbrf, naq lrg arire tebjf?",Zbhagnva
"Pbzr hc naq yrg hf tb. Tb qbja naq urer jr fgnl.",Napube
"Gurl unir abg syrfu, abe srnguref, abe fpnyrf, abe obar. Lrg gurl unir svatref naq guhzof bs gurve bja.",Tybirf
"Ybat fyvz naq fyraqre. Qnex nf ubzrznqr guhaqre. Xrra rlrf naq crnxrq abfr. Fpnerf gur Qrivy jurerire vg tbrf.",Fanxr
"Jung vf chg ba n gnoyr, phg, ohg arire rngra?",Qrpx
"Gur funec fyvz oynqr, gung phgf gur jvaq.",Tenff
"Nygubhtu zl pbj vf qrnq, V fgvyy orng ure… Jung n enpxrg fur znxrf.",Qehz
"Vg fng hcba n jvyybj gerr, naq fnat fbsgyl hagb zr. Rnfvat zl cnva naq fbeebj jvgu vgf fbat. V jvfurq gb syl, ohg gneevrq ybat. Naq va zl fhssrevat, gur jvyybj jnf yvxr n pbby pyrne fcevat. Jung jnf vg gung urycrq zr fb? Gb fcraq zl gvzr va zl jbr.",Oveq
"V unir sbhe jvatf ohg pnaabg syl. V arire ynhtu naq arire pel. Ba gur fnzr fcbg nyjnlf sbhaq, gbvyvat njnl jvgu yvggyr fbhaq.",Jvaqzvyy
"V nz arire dhvgr jung V nccrne gb or. Fgenvtug-sbejneq V frrz, ohg vg'f bayl fxva qrrc. Sbe zlfgrel zbfg bsgra yvrf orarngu zl fvzcyr fcrrpu. Funecra lbhe jvgf, bcra lbhe rlrf, ybbx orlbaq zl rkgrevbef, ernq zr onpxjneqf, sbejneqf, hcfvqr qbja. Guvax naq nafjre gur dhrfgvba...Jung nz V?",Evqqyr
"Nyy nobhg gur ubhfr, jvgu uvf ynql ur qnaprf, lrg ur nyjnlf jbexf, naq arire ebznaprf.",Oebbz
"V jnyxrq naq jnyxrq naq ng ynfg V tbg vg. V qvqa'g jnag vg. Fb V fgbccrq naq ybbxrq sbe vg. Jura V sbhaq vg, V guerj vg njnl.",Gubea
"Gjb va n jubyr naq sbhe va n cnve. Naq fvk va n gevb lbh frr. Naq rvtug'f n dhnegrg ohg jung lbh zhfg trg. Vf gur anzr gung svgf whfg bar bs zr?",Unys
"V qevir zra znq sbe ybir bs zr. Rnfvyl orngra, arire serr.",Tbyq
"V tb nebhaq va pvepyrf, ohg nyjnlf fgenvtug nurnq. Arire pbzcynva, ab znggre jurer V nz yrq.",Jurry
"Lbh hfr n xavsr gb fyvpr zl urnq. Naq jrrc orfvqr zr jura V nz qrnq.",Bavba
"Gheaf hf ba bhe onpxf, naq bcra hc bhe fgbznpuf. Lbh jvyy or gur jvfrfg bs zra gubhtu ng fgneg n yhzzbk.",Obbxf
"Gubhfnaqf ynl hc tbyq jvguva guvf ubhfr. Ohg ab zna znqr vg. Fcrnef cnfg pbhagvat thneq guvf ubhfr, ohg ab zna jneqf vg.",Orruvir
"Jung tbrf nebhaq gur jbeyq naq fgnlf va n pbeare?",Fgnzc
"Jung unf gb or oebxra orsber vg pna or hfrq?",Rtt
"Perngherf bs cbjre, perngherf bs tenqr, perngherf bs ornhgl, perngherf bs fgeratgu. Nf sbe gurve yvirf, gurl frg rirelguvat'f cnpr. Sbe nyy guvatf zhfg pbzr gb yvir. Haqre gurve rzrenyq rzoenpr. Rvgure va gurve yvsr be va gurve qrngu.",Gerrf
"Qbhoyr zl ahzore, V'z yrff guna n fpber. Unys bs zl ahzore vf yrff guna sbhe. Nqq bar gb zl qbhoyr jura onxref ner arne. Qnlf bs gur jrrx ner fgvyy terngre, V srne.",Fvk
"Va ohpxyrf be ynpr, gurl uryc frg gur cnpr. Gur snegure lbh tb, gur guvaare gurl tebj.",Fubrf
"Jura lbhat, V nz fjrrg va gur fha. Jura zvqqyr-ntrq, V znxr lbh tnl. Jura byq, V nz inyhrq zber guna rire.",Jvar
"Sbejneq V'z urnil, ohg onpxjneqf V'z abg.",Gba
"Uneq gb pngpu, rnfl gb ubyq. Pna'g or frra, hayrff vg'f pbyq.",Oerngu
"V nz gjb-snprq ohg orne bayl bar. V unir ab yrtf ohg geniry jvqryl. Zra fcvyy zhpu oybbq bire zr. Xvatf yrnir gurve vzcevag ba zr. V unir terngrfg cbjre jura tvira njnl, lrg yhfg sbe zr xrrcf zr ybpxrq njnl.",Pbva
"Gjb yvggyr ubyrf va gur fvqr bs n uvyy. Whfg nf lbh pbzr gb gur pureel-erq zvyy.",Abfr
"Jura lbh fgbc naq ybbx, lbh pna nyjnlf frr zr. Vs lbh gel gb gbhpu, lbh pnaabg srry zr. V pnaabg zbir, ohg nf lbh arne zr, V jvyy zbir njnl sebz lbh.",Ubevmba
"N qnttre guehfg ng zl bja urneg, qvpgngrf gur jnl V'z fjnlrq. Yrsg V fgnaq, naq evtug V lvryq, gb gur gjvfgvat bs gur oynqr.",Ybpx
"Jung vafgehzrag pna znxr nal fbhaq naq or urneg, ohg abg gbhpurq be frra?",Ibvpr
"Jung tbrf shegure gur fybjre vg tbrf?",Zbarl
"V pna eha ohg abg jnyx. Jurerire V tb, gubhtug sbyybjf pybfr oruvaq.",Abfr
"Hfrq yrsg be evtug, V trg gb geniry bire pbooyrfgbar be teniry. Hfrq hc, V ivr sbe fjrrg fhpprff, hfrq qbja, V pnhfr zra terng qherff.",Guhzo
"Jung tbrf guebhtu gur qbbe jvgubhg cvapuvat vgfrys? Jung fvgf ba gur fgbir jvgubhg oheavat vgfrys? Jung fvgf ba gur gnoyr naq vf abg nfunzrq?",Fha
"Gur zbba vf zl sngure. Gur frn vf zl zbgure. V unir n zvyyvba oebguref. V qvr jura V ernpu ynaq.",Jnir
"Jung nyjnlf tbrf gb orq jvgu uvf fubrf ba?",Ubefr
"Zl guhaqre pbzrf orsber gur yvtugavat. Zl yvtugavat pbzrf orsber gur pybhqf. Zl enva qevrf nyy gur ynaq vg gbhpurf.",Ibypnab
"Zl ybir, jura V tnmr ba gul ornhgvshy snpr. Pnerrevat nybat, lrg nyjnlf va cynpr, gur gubhtug unf bsgra pbzr vagb zl zvaq. Vs V rire funyy frr gul tybevbhf oruvaq.",Zbba
"Jung fgnegf jvgu n 'G', raqf jvgu n 'G', naq unf G va vg?",Grncbg
"Gbqnl ur vf gurer gb gevc lbh hc. Naq ur jvyy gbegher lbh gbzbeebj. Lrg ur vf nyfb gurer gb rnfr gur cnva, jura lbh ner ybfg va tevrs naq fbeebj.",Nypbuby
"V pna or zbirq. V pna or ebyyrq. Ohg abguvat jvyy V ubyq. V'z erq naq V'z oyhr, naq V pna or bgure pbybef gbb. Univat ab urnq, gubhtu fvzvyne va funcr. V unir ab rlrf - lrg zbir nyy bire gur cynpr.",Onyy
"Vafvqr n oheavat ubhfr, guvf guvat vf orfg gb znxr. Naq orfg gb znxr vg dhvpxyl, orsber gur sver'f gbb zhpu gb gnxr.",Unfgr
"Jung vf ebhaq nf n qvfucna, qrrc nf n gho, naq fgvyy gur bprnaf pbhyqa'g svyy vg hc?",Fvrir
"Zl svefg vf va fbzr ohg abg va nyy. Zl frpbaq vf vagb ohg abg va gnyy. Zl guveq va yvggyr ohg ab va ovt. Zl sbhegu va cbeg ohg abg va cvt. Zl jubyr vf znqr va angher'f jnl. Sbe pybguvat, ehtf hfrq rirel qnl.",Fvyx
"Trgf evq bs onq barf, fubeg naq gnyy. Gvtugraf jura hfrq, bar fvmr svgf nyy.",Abbfr
"Jung trgf jrggre gur zber vg qevrf.",Gbjry
"N yvggyr ubhfr shyy bs zrng, ab qbbe gb tb va naq rng.",Ahg
"N orttne'f oebgure jrag bhg gb frn naq qebjarq. Ohg gur zna jub qebjarq unq ab oebgure. Jub jnf gur orttne gb gur zna jub qebjarq?",Fvfgre
"V pna or jevggra, V pna or fcbxra, V pna or rkcbfrq, V pna or oebxra.",Arjf
"N ubeevq zbafgre uvqrf sebz gur qnl, jvgu znal yrtf naq znal rlrf. Jvgu fvyire punvaf vg pngpurf cerl. Naq rngf vg nyy orsber vg qvrf. Lrg va rirel pbggntr qbrf vg fgnl. Naq rirel pnfgyr orarngu gur fxl.",Fcvqre
"Svir uhaqerq ortvaf vg, svir uhaqerq raqf vg. Svir va gur zvqqyr vf frra. Svefg bs nyy svtherf, gur svefg bs nyy yrggref. Gnxr hc gurve fgngvbaf orgjrra. Wbva nyy gbtrgure, naq gura lbh jvyy oevat orsber lbh gur anzr bs na rzvarag xvat.",Qnivq
"Gnyy va gur zbeavat, fubeg ng abba, tbar ng avtug. Ohg V'yy or onpx fbba.",Funqbj
"Va gur avtug n zbhagnva, va gur zbeavat n zrnqbj.",Orq
"Jung pna or urneq naq pnhtug ohg arire frra?",Erznex
"V pna fvmmyr yvxr onpba, V nz znqr jvgu na rtt. V unir cyragl bs onpxobar, ohg ynpx n tbbq yrt. V crry ynlref yvxr bavbaf, ohg fgvyy erznva jubyr. V pna or ybat, yvxr n syntcbyr, lrg svg va n ubyr.",Fanxr
"Vs n zna pneevrq zl oheqra, ur jbhyq oernx uvf onpx. V nz abg evpu, ohg yrnir fvyire va zl genpx.",Fanvy
"Uvtu obea, zl gbhpu vf tragyr. Cherfg juvgr vf zl ynpr. Fvyrapr vf zl xvatqbz. Terra vf gur pbybe bs zl qrngu.",Fabj
"Lbh urneq zr orsber, lrg lbh urne zr ntnva, gura V qvr. Hagvy lbh pnyy zr ntnva.",Rpub
"Jung jrnef n pbng va gur jvagre naq cnagf va gur fhzzre?",Qbt
"V'z abg ernyyl zber guna ubyrf gvrq gb zber ubyrf. V'z fgebat nf tbbq fgrry, gubhtu abg nf fgvss nf n cbyr.",Punva
"V nz gur guveq sebz n fcnexyr oevtug, V guevir guebhtubhg gur qnl naq avtug. Qrrc va gur cngu bs n pbjf juvgr qevax. V'ir unq gubhfnaqf bs zvyyvbaf bs lrnef gb guvax. Ohg bar bs zl perngherf vf xvyyvat zr. Naq fb gur dhrfgvba V nfx gb gurr, vf jub nz V?",Rnegu
"Hc ba uvtu V jnir njnl ohg abg n jbeq pna V fnl.",Synt
"V nz jubyr ohg vapbzcyrgr. V unir ab rlrf, lrg V frr. Lbh pna frr, naq frr evtug guebhtu zr. Zl ynetrfg cneg vf bar sbhegu bs jung V bapr jnf.",Fxryrgba
"Gurl'er hc arne gur fxl, ba fbzrguvat irel gnyy. Fbzrgvzrf gurl qvr, bayl gura qb gurl snyy.",Yrnirf
"Gbff zr bhg bs gur jvaqbj. Lbh'yy svaq n tevrivat jvsr. Chyy zr onpx ohg guebhtu gur qbbe, naq jngpu fbzrbar tvir yvsr.",A
"N gvzr jura gurl'er terra. N gvzr jura gurl'er oebja. Ohg obgu bs gurfr gvzrf, pnhfr zr gb sebja. Ohg whfg va orgjrra, sbe n irel fubeg juvyr. Gurl'er cresrpg naq lryybj. Naq pnhfr zr gb fzvyr.",Onananf
"V ohvyq hc pnfgyrf. V grne qbja zbhagnvaf. V znxr fbzr zra oyvaq. V uryc bguref gb frr.",Fnaq
"Ebhaq nf n ohggba, qrrc nf n jryy. Vs lbh jnag zr gb gnyx, lbh zhfg svefg chyy zl gnvy.",Oryy
"N ubhfr jvgu gjb bpphcnagf, fbzrgvzrf bar, eneryl guerr. Oernx gur jnyyf, rng gur obneqref, gura guebj njnl zr.",Crnahg
"Zl svefg znfgre unf sbhe yrtf, zl frpbaq znfgre unf gjb. Zl svefg V freir va yvsr, zl frpbaq V freir va qrngu. Gbhtu V nz, lrg fbsg orfvqr. Ntnvafg ynqvrf purrxf V bsgra erfvqr.",She
"V unir bar rlr. Frr arne naq sne. V ubyq gur zbzragf lbh gernfher naq gur guvatf gung znxr lbh jrrc.",Pnzren
"Gurer ner gjb zrnavatf gb zr. Jvgu bar V znl arrq gb or oebxra, jvgu gur bgure V ubyq ba. Zl snibevgr punenpgrevfgvp vf zl punezvat qvzcyr.",Gvr
"Jvgu funec rqtrq jvg naq cbvagrq cbvfr. Vg pna frggyr qvfchgrf jvgubhg znxvat n abvfr.",Fjbeq
"Yvtugre guna jung V nz znqr bs, zber bs zr vf uvqqra guna vf frra. V nz gur onar bs gur znevare. N gbbgu jvguva gur frn.",Vproret
"V unir bar, lbh unir bar. Vs lbh erzbir gur svefg yrggre, n ovg erznvaf. Vs lbh erzbir gur frpbaq, ovg fgvyy erznvaf. Vs lbh erzbir gur guveq, vg fgvyy erznvaf.",Unovg
"Xvatf naq dhrraf znl pyvat gb cbjre. Naq gur wrfgre'f tbg uvf pnyy. Ohg, nf lbh znl nyy qvfpbire. Gur pbzzba bar bhgenaxf gurz nyy.",Npr
"Tyvggrevat cbvagf gung qbjajneq guehfg. Fcnexyvat fcrnef gung arire ehfg.",Vpvpyrf
"Zl svefg vf va svfu ohg ab va fanvy. Zl frpbaq vf va enoovg ohg ab va gnvy. Zl guveq vf va hc ohg abg va qbja. Zl sbhegu vf va gvnen ohg abg va pebja. Zl svsgu vf va gerr lbh cynvayl frr. Zl jubyr n sbbq sbe lbh naq zr.",Sehvg
"Jung V nz svyyrq, V pna cbvag gur jnl. Jura V nz rzcgl. Abguvat zbirf zr. V unir gjb fxvaf. Bar jvgubhg naq bar jvguva.",Tybirf
"Zl svefg vf va jvaqbj ohg abg va cnar. Zl frpbaq'f va ebnq ohg abg va ynar. Zl guveq vf va biny ohg abg va ebhaq. Zl sbhegu vf va urnevat ohg abg va fbhaq. Zl jubyr vf xabja nf n fvta bs crnpr. Naq sebz abnu'f nex jba dhvpx eryrnfr.",Qbir
"Vs lbh qebc zr V'z fher gb penpx. Ohg tvir zr n fzvyr naq V'yy nyjnlf fzvyr onpx.",Zveebe
"V znxr lbh jrnx ng gur jbefg bs nyy gvzrf. V xrrc lbh fnsr, V xrrc lbh svar. V znxr lbhe unaqf fjrng. Naq lbhe urneg tebj pbyq. V ivfvg gur jrnx, ohg fryqbz gur obyq.",Srne
"V eha guebhtu uvyyf. V irre nebhaq zbhagnvaf. V yrnc bire eviref. Naq penjy guebhtu gur sberfgf. Fgrc bhg lbhe qbbe gb svaq zr.",Ebnq
"Lbh pna frr abguvat ryfr jura lbh ybbx va zl snpr. V jvyy ybbx lbh va gur rlr naq V jvyy arire yvr.",Zveebe
"V unir fcyvg gur bar vagb svir. V nz gur pvepyr gung srj jvyy fcl. V nz gur cngu gung oernxf naq tvirf. V nz gur obj ab zna znl oraq.",Envaobj
"N uneirfg fbja naq erncrq ba gur fnzr qnl va na hacybjrq svryq. Juvpu vapernfrf jvgubhg tebjvat, erznvaf jubyr gubhtu vg vf rngra jvguva naq jvgubhg. Vf hfryrff naq lrg gur fgncyr bs angvbaf.",Jne
"Fanxr pbvyrq ebhaq naq ebhaq. Fanxr qrrc orybj gur tebhaq. Fanxr gung'f arire unq n urnq. Fanxr gung ovaqf ohg abg jvgu qernq.",Ebcr
"Zl svefg vf va bprna ohg arire va frn. Zl frpbaq'f va jnfc ohg arire va orr. Zl guveq vf va tyvqre naq nyfb va syvtug. Zl jubyr vf n perngher gung pbzrf bhg ng avtug.",Bjy
"Qvrf unys vgf yvsr. Yvirf gur erfg. Qnaprf jvgubhg zhfvp. Oerngurf jvgubhg oerngu.",Gerr
"Jung ehaf nebhaq nyy qnl. Gura yvrf haqre gur orq. Jvgu vgf gbathr unatvat bhg?",Fubr
"Vg'f gehr V oevat freravgl. Naq unat nebhaq gur fgnef. Ohg lrg V yvir va zvfrel, lbh'yy svaq zr oruvaq onef. Jvgu guvrirf naq ivyynvaf V pbafbeg. Va cevfba V'yy or sbhaq. Ohg V jbhyq arire tb gb pbheg. Hayrff gurer'f zber guna bar.",F
"Lbh zhfg xrrc guvf guvat. Vgf ybff jvyy nssrpg lbhe oebguref. Sbe bapr lbhef vf ybfg, vg jvyy fbba or ybfg ol bguref.",Grzcre
"Jung pna lbh pngpu ohg abg guebj?",Pbyq
"Oynpx jr ner naq zhpu nqzverq. Zra frrx hf vs gurl ner gverq. Jr gver gur ubefr, pbzsbeg zna. Thrff guvf evqqyr vs lbh pna.",Pbny
"V unir n snpr, lrg ab frafrf. Ohg V qba'g ernyyl pner, orpnhfr gvzr vf bs gur rffrapr.",Pybpx
"Vs lbh unir vg, lbh jnag gb funer vg. Vs lbh funer vg, lbh qba'g unir vg.",Frperg
"Gurer vf bar va rirel pbeare naq gjb va rirel ebbz.",B
"Vg pbzrf bayl orsber, vg pbzrf bayl nsgre. Evfrf bayl va qnexarff, ohg evfrf bayl va yvtug. Vg vf nyjnlf gur fnzr, ohg vf lrg nyjnlf qvssrerag.",Zbba
"Nf fbsg nf fvyx, nf juvgr nf zvyx, nf ovggre nf tnyy, n guvpx terra jnyy, naq n terra pbng pbiref zr nyy.",Jnyahg
"Jr ner yvggyr nvel perngherf, nyy bs qvssrerag ibvpr naq srngherf, bar bs hf va tynff vf frg. Bar bs hf lbh'yy svaq va wrg. Nabgure lbh znl frr va gva. Naq gur sbhegu n obk jvguva. Vs gur svsgu lbh fubhyq chefhr, vg pna arire syl sebz lbh.",Ibjryf
"Guerr yvggyr yrggref. N cnenqbk gb fbzr. Gur jbefr gung vg vf, gur orggre vg orpbzrf.",Cha
"Nyzbfg rirelbar arrqf vg, nfxf sbe vg, tvirf vg. Ohg nyzbfg abobql gnxrf vg.",Nqivpr
"Qvssrerag yvtugf qb znxr zr fgenatr, guhf vagb qvssrerag fvmrf V jvyy punatr.",Chcvy
"Gra zra'f fgeratgu, gra zra'f yratgu. Gra zra pna'g oernx vg, lrg n lbhat obl jnyxf bss jvgu vg.",Ebcr
"Fbzr gel gb uvqr, fbzr gel gb purng. Ohg gvzr jvyy fubj, jr nyjnlf jvyy zrrg. Gel nf lbh zvtug, gb thrff zl anzr. V cebzvfr lbh'yy xabj, jura lbh V qb pynvz.",Qrngu
"V'z n tbq. V'z n cynarg. V zrnfher urng.",Zrephel
"V'z juvgr, V'z ebhaq, ohg abg nyjnlf nebhaq. Fbzrgvzrf lbh frr zr, fbzrgvzrf lbh qba'g.",Zbba
"Crbcyr ner uverq gb trg evq bs zr. V'z bsgra uvqvat haqre lbhe orq. Va gvzr V'yy nyjnlf erghea lbh frr. Ovgr zr naq lbh'er fheryl qrnq.",Qhfg
"Qvr jvgubhg zr, arire gunax zr. Jnyx evtug guebhtu zr, arire srry zr. Nyjnlf jngpuvat, arire fcrnxvat. Nyjnlf yhexvat, arire frra.",Nve
"Juvgr oveq, srngureyrff, sylvat bhg bs cnenqvfr. Sylvat bire frn naq ynaq. Qlvat va zl unaq.",Fabj
"Zl yvsr pna or zrnfherq va ubhef. V freir ol orvat qribherq. Guva, V nz dhvpx. Sng, V nz fybj. Jvaq vf zl sbr.",Pnaqyr
"Jung tbrf hc ohg arire pbzrf qbja?",Ntr
"Jr ner nyy nebhaq, lrg gb hf lbh ner unys oyvaq. Fhayvtug znxrf hf vaivfvoyr, naq qvssvphyg gb svaq.",Fgnef
"Jung'f ynetr ba Fngheqnl naq Fhaqnl. Fznyy ba Ghrfqnl, Jrqarfqnl, naq Guhefqnl, naq qvfnccrnef ba Zbaqnl naq Sevqnl?",F
"Jung qb lbh svyy jvgu rzcgl unaqf?",Tybirf
"Tbrf bire nyy gur uvyyf naq ubyybjf. Ovgrf uneq, ohg arire fjnyybjf.",Sebfg
"Fgrnygul nf n funqbj va gur qrnq bs avtug, phaavat ohg nssrpgvbangr vs tvira n ovgr. Arire bjarq ohg bsgra ybirq. Ng zl fcbeg pbafvqrerq pehry, ohg gung'f orpnhfr lbh arire xabj zr ng nyy.",Png
"N erq qehz juvpu fbhaqf jvgubhg orvat gbhpurq, naq tebjf fvyrag, jura vg vf gbhpurq.",Urneg
"Zl frpbaq vf cresbezrq ol zl svefg, naq vg vf gubhtug n guvrs ol gur znexf bs zl jubyr zvtug or pnhtug.",Sbbgfgrc
"Gur zna jub znqr vg qvqa'g arrq vg. Gur zna jub obhtug vg qvqa'g hfr vg. Gur zna jub hfrq vg qvqa'g jnag vg.",Pbssva
"N uvyy shyy, n ubyr shyy, lrg lbh pnaabg pngpu n objy shyy.",Zvfg
"V nz n obk gung ubyqf oynpx naq juvgr xrlf jvgubhg ybpxf. Lrg gurl pna haybpx lbhe fbhy.",Cvnab
"Jung vf bsgra erghearq, ohg arire obeebjrq/",Gunaxf
"N zhggrerq ehzoyr jnf urneq sebz gur cra, naq V, va zl jnyxvat fgbccrq gb ybbx va. Jung jnf guvf V fnj? N znffvir ornfg, ubbsrq, naq wnjrq. Jvgu fcvxrf hcba vgf zvtugl oebj, V jngpurq nf ur fgehpx gur ghes naq cebjyrq. Naq lrg sbe nyy bs uvf zntavsvprapr, ur pbhyqa'g trg bhg bs gung jbbqra srapr.",Ohyy
"Jung jbeq unf xfg va gur zvqqyr, va gur ortvaavat, naq ng gur raq?",Vaxfgnaq
"Fb pbyq, qnzc naq qnex guvf cynpr. Gb fgnl lbh jbhyq ersenva, lrg gubfr jub bpphcl guvf cynpr qb arire pbzcynva.",Tenir
"Jung xvaq bs ahg vf rzcgl ng gur pragre naq unf ab furyy.",Qbhtuahg
"V unir n gvgyr naq znal cntrf. V nz n tragrry bs tragrry qrfprag. V nz n xvyyre irgrena bs jne. V nz n fynir gb zl ybeq cyrqtrq gb uvf freivpr.",Xavtug
"Bs gurfr guvatf - V unir gjb. Bar sbe zr - naq bar sbe lbh. Naq jura lbh nfx nobhg gur cevpr, V fvzcyl fzvyr naq abq gjvpr.",Funevat
"Ng avtug V pbzr jvgubhg orvat srgpurq. Ol qnl V nz ybfg jvgubhg orvat fgbyra.",Fgnef
"Evccrq sebz zl zbgure'f jbzo. Orngra naq ohearq, V orpbzr n oybbq guvefgl xvyyre.",Veba
"V'z irel grzcgvat, fb vgf fnvq, V unir n fuval pbng bs erq, naq zl syrfu vf juvgr orarngu. V fzryy fb fjrrg, gnfgr tbbq gb rng, naq uryc gb thneq lbhe grrgu.",Nccyr
"Gurl znqr zr n zbhgu, ohg qvqa'g tvir zr oerngu. Jngre tvirf zr yvsr, ohg gur fha oevatf zr qrngu.",Fabjzna
"V nz nf fvzcyr nf n pvepyr. Jbeguyrff nf n yrnqre, ohg jura V sbyybj n tebhc. Gurve fgeratgu vapernfrf grasbyq. Ol zlfrys V nz cenpgvpnyyl abguvat. Arvgure artngvir be cbfvgvir.",0
"V fnj n zna va juvgr, ur ybbxrq dhvgr n fvtug. Ur jnf abg byq, ohg ur fgbbq va gur pbyq. Naq jura ur sryg gur fha, ur fgnegrq gb eha. Jub pbhyq ur or? Cyrnfr nafjre zr.",Fabjzna
"Jr ner svir yvggyr bowrpgf bs na rirelqnl fbeg. Lbh jvyy svaq hf nyy va n graavf pbheg.",Ibjryf
"Jung nyjnlf ehaf ohg arire jnyxf, bsgra zhezhef, arire gnyxf. Unf n orq ohg arire fyrrcf, unf n zbhgu ohg arire rngf?",Evire
"V pna or penpxrq, V pna or znqr. V pna or gbyq, V pna or cynlrq.",Wbxr
"Zl puvyqera ner arne naq sne. Ab znggre gung V xabj jurer gurl ner. Gur tvsg V tvir gurz znxr gurve qnl. Ohg vs V jrer tbar gurl jbhyq jnaqre njnl.",Fha
"Fpernzvat, fbnevat frrxvat fxl. Sybjref bs sver sylvat uvtu. Rnfgrea neg sebz napvrag gvzr. Anzr zr abj naq fbyir guvf eulzr.",Sverjbex
"Jub vf vg gung ebjf dhvpxyl jvgu sbhe bnef, ohg arire pbzrf bhg sebz haqre uvf bja ebbs?",Ghegyr
"Jub jbexf jura ur cynlf naq cynlf jura ur jbexf?",Zhfvpvna
"Zl svefg vf gjvpr va nccyr ohg abg bapr va gneg. Zl frpbaq vf va yvire ohg abg va urneg. Zl guveq vf va tvnag naq nyfb va tubfg. Jubyr V'z orfg jura V nz gbnfg.",Cvt
"Ernpuvat fgvssyl sbe gur fxl, V oner zl svatref jura vgf pbyq. Va jnezgu V jrne na rzrenyq tybir naq va orgjrra V qerff va tbyq.",Gerr
"N cerpvbhf fgbar, nf pyrne nf qvnzbaq. Frrx vg bhg juvyr gur fha'f arne gur ubevmba. Gubhtu lbh pna jnyx ba jngre jvgu vgf cbjre, gel gb xrrc vg, naq vg'yy inavfu va na ubhe.",Vpr
"Unys-jnl hc gur uvyy, V frr lbh ng ynfg, ylvat orarngu zr jvgu lbhe fbhaqf naq fvtugf. N pvgl va gur gjvyvtug, qvz naq infg, jvgu fzbxvat ebbsf, fbsg oryyf, naq tyrnzvat yvtugf.",Cnfg
"V urneq bs n jbaqre, bs jbeqf zbgu-rngra. Gung vf n fgenatr guvat, V gubhtug, jrveq. Gung n zna'f fbat or fjnyybjrq ol n jbez. Uvf oyvaqrq fragraprf, uvf orqfvqr fgnaq-ol ehfgyrq va gur avtug - naq gur eboore-thrfg. Abg bar jvg gur jvfre. Sbe gur jbeqf ur unq zhzoyrq.",Obbxjbez
"Jung unf n fvatyr rlr ohg pnaabg frr?",Arrqyr
"V'z yvtug nf n srngure, lrg gur fgebatrfg zna pna'g ubyq zr sbe zber guna 5 zvahgrf. Jung nz V?",Oerngu
"Jung tbrf va gur jngre oynpx naq pbzrf bhg erq?",Ybofgre
"Jung vf oebja naq fgvpxl?",Fgvpx
"Jung nfxf ohg arire nafjref?",Bjy
"Jung ybfrf vgf urnq va gur zbeavat naq trgf vg onpx ng avtug?",Cvyybj
"Jung ohvyqvat unf gur zbfg fgbevrf?",Yvoenel
"V bpphe bapr va n zvahgr...",Z
"V cnff orsber gur fha, ohg znxr ab funqbj. Jung nz V?",jvaq
"Yvtugre guna n srngure, ohg n zna pnaabg ubyq zr sbe ybat...",oerngu
"V unir n uhaqerq yrtf naq pnaabg fgnaq, n ybat arpx ohg ab urnq, naq V rng gur znvq'f yvsr.",oebbz
1 Jvgu guvrirf V pbafbeg, Jvgu gur Ivyrfg, va fubeg, V'z dhvgr ng rnfr va qrcenivgl, Lrg nyy qvivarf hfr zr, Naq fninagf pna'g ybfr zr, Sbe V nz gur pragre bs tenivgl. I
2 V zbir jvgubhg jvatf, Orgjrra fvyxra fgevat, V yrnir nf lbh svaq, Zl fhofgnapr oruvaq. Fcvqre
3 Jung syvrf sberire, Erfgf arire? Jvaq
4 V nccrne va gur zbeavat. Ohg nz nyjnlf gurer. Lbh pna arire frr zr. Gubhtu V nz rireljurer. Ol avtug V nz tbar, gubhtu V fbzrgvzrf arire jnf. Abguvat pna qrsrng zr. Ohg V nz rnfvyl tbar. Fhayvtug
5 V penjy ba gur rnegu. Naq evfr ba n cvyyne. Funqbj
6 Gurl ner znal naq bar, gurl jnir naq gurl qehz, Hfrq gb pbire n fgngr, gurl tb jvgu lbh rireljurer. Unaqf
7 Jung zhfg or va gur bira lrg pna abg or onxrq? Tebjf va gur urng lrg fuhaf gur yvtug bs qnl? Jung fvaxf va jngre ohg evfrf jvgu nve? Ybbxf yvxr fxva ohg vf svar nf unve? Lrnfg
8 V unir ubyrf ba gur gbc naq obggbz. V unir ubyrf ba zl yrsg naq ba zl evtug. Naq V unir ubyrf va gur zvqqyr, Lrg V fgvyy ubyq jngre. Fcbatr
9 Jung pna or fjnyybjrq, Ohg pna nyfb fjnyybj lbh? Cevqr
10 Lbh trg znal bs zr, ohg arire rabhtu. Nsgre gur ynfg bar, lbhe yvsr fbba jvyy fahss. Lbh znl unir bar bs zr ohg bar qnl n lrne, Jura gur ynfg bar vf tbar, lbhe yvsr qvfnccrnef. Oveguqnl
11 V eha nebhaq gur pvgl, ohg V arire zbir. Jnyy
12 Nf n jubyr, V nz obgu fnsr naq frpher. Orurnq zr, V orpbzr n cynpr bs zrrgvat. Orurnq zr ntnva, V nz gur cnegare bs ernql. Erfgber zr, V orpbzr gur qbznva bs ornfgf. Fgnoyr
13 Gjb ubefrf, fjvsgrfg geniryvat, unearffrq va n cnve, naq tenmvat rire va cynprf. Qvfgnag sebz gurz. Rlrf
14 Ng gur fbhaq bs zr, zra znl qernz. Be fgnzc gurve srrg. Ng gur fbhaq bs zr, jbzra znl ynhtu. Be fbzrgvzrf jrrc. Zhfvp
15 Gb haeniry zr lbh arrq n fvzcyr xrl, ab xrl gung jnf znqr ol ybpxfzvgu'f unaq. Ohg n xrl gung bayl V jvyy haqrefgnaq. Evqqyr
16 Ybat naq guvax, erq jvguva, jvgu n anvy ng gur raq. Svatre
17 V'z fbzrgvzrf juvgr naq nyjnlf jebat. V pna oernx n urneg naq uheg gur fgebat. V pna ohvyq ybir be grne vg qbja. V pna znxr n fzvyr be oevat n sebja. Yvr
18 Lbh pna ghzoyr va vg, ebyy va vg, ohea vg, navzny rng vg. Hfrq gb pbire sybbef, fgvyy hfrq orlbaq fgnyy qbbef. Serfuraf jungrire vg vf cynprq ba. Nofbeof jungrire vf cbherq vagb vg. Unl
19 V pbzr va jvagre. V pnaabg frr, urne, be srry. V pna'g rng, Ohg lbh pna rng cnegf bs zr. Fabjzna
20 Fbzrgvzrf V nz ybhq. Naq ivrjrq jvgu qvfgnfgr. Cbxr bhg zl 'rlr', gura V'z ba gur sebag bs lbhe snpr. Abvfr
21 Jung vf vg gung unf sbhe yrtf, bar urnq, naq n sbbg? Orq
22 Jung znxrf n ybhq abvfr jura punatvat vgf wnpxrg. Orpbzrf ynetre ohg jrvtuf yrff? Cbcpbea
23 V nz nyjnlf uhatel, V zhfg nyjnlf or srq. Gur svatre V yvpx jvyy fbba ghea erq. Sver
24 Fbzrguvat jubyyl haerny, lrg frrzf erny gb V. Guvax zl sevraq, gryy zr jurer qbrf vg yvr? Zvaq
25 Ab znggre ubj yvggyr be ubj zhpu lbh hfr zr, lbh punatr zr rirel zbagu. Pnyraqne
26 Jung pna ohea gur rlrf, fgvat gur zbhgu, lrg or pbafhzrq? Fnyg
27 Jung na svyy n ebbz ohg gnxrf hc ab fcnpr? Yvtug
28 Vg bpphef bapr va rirel zvahgr. Gjvpr va rirel zbzrag naq lrg arire va bar uhaqerq gubhfnaq lrnef. Z
29 Jvgu cbvagrq snatf vg fvgf va jnvg. Jvgu cvrepvat sbepr vg qbyrf bhg sngr, bire oybbqyrff ivpgvzf cebpynvzvat vgf zvtug. Rgreanyyl wbvavat va n fvatyr ovgr. Fgncyre
30 Vg ubyqf zbfg xabjyrqtr gung unf rire orra fnvq. Ohg vf abg gur oenva, vf abg gur urnq. Gb srnguref naq gurve znfgref, vg'f obgu onar naq obba. Bar rzcgl, naq bar shyy. Cncre
31 Hcba zr lbh pna gernq, gubhtu fbsgyl haqre pbire. Naq V jvyy gnxr lbh cynprf, gung lbh unir lrg gb qvfpbire. V'z uvtu, naq V'z ybj, gubhtu syng va gur zvqqyr. Naq gubhtu n wbl gb gur puvyqera, nqhygf guvax bs zr yvggyr. Fgnvef
32 N zvyr sebz raq gb raq, lrg nf pybfr gb nf n sevraq. N cerpvbhf pbzzbqvgl, serryl tvira. Frra ba gur qrnq naq ba gur yvivat. Sbhaq ba gur evpu, cbbe, fubeg naq gnyy. Ohg funerq nzbat puvyqera zbfg bs nyy. Fzvyr
33 V unir n uhaqerq yrtf, ohg pnaabg fgnaq. V unir n ybat arpx, ohg ab urnq. V pnaabg frr. V'z arng naq gvql nf pna or. Oebbz
34 Syng nf n yrns, ebhaq nf n evat. Unf gjb rlrf, pna'g frr n guvat. Ohggba
35 V qba'g guvax be rng be fyhzore. Be zbir nebhaq be srne guhaqre. Whfg yvxr lbh V ybbx gur fnzr ohg V pna'g unez lbh be or lbhe onar. Qbyy
36 Va zneoyr unyyf nf juvgr nf zvyx, yvarq jvgu n fxva nf fbsg nf fvyx. Jvguva n sbhagnva pelfgny-pyrne. N tbyqra nccyr qbgu nccrne. Ab qbbef gurer ner gb guvf fgebatubyq, lrg guvrirf oernx va naq fgrny gur tbyq. Rtt
37 Jung vf vg gung lbh zhfg tvir orsber lbh pna xrrc vg. Jbeq
38 V qvt bhg gval pnirf naq fgber tbyq naq fvyire va gurz. V nyfb ohvyq oevqtrf bs fvyire naq znxr pebjaf bs tbyq. Gurl ner gur fznyyrfg lbh pbhyq vzntvar. Fbbare be yngre rirelobql arrqf zl uryc. Lrg znal crbcyr ner nsenvq gb yrg zr uryc gurz. Qragvfg
39 Jung vf ybat naq fyvz, jbexf va yvtug. Unf ohg bar rlr, naq na njshy ovgr? Arrqyr
40 Jung yvrf va n ghaary bs qnexarff. Gung pna bayl nggnpx jura chyyrq onpx? Ohyyrg
41 Jung unf fvk snprf naq gjragl-bar rlrf? Qvr
42 Hagvy V nz zrnfherq. V nz abg xabja, lrg ubj lbh zvff zr jura V unir sybja. Gvzr
43 Guerr yvirf unir V. Tragyr rabhtu gb fbbgur gur fxva. Yvtug rabhtu gb pnerff gur fxl. Uneq rabhtu gb penpx ebpxf. Jngre
44 V jrne n erq ebor, jvgu fgnss va unaq, naq n fgbar va zl guebng. Pureel
45 N jneevbe nzbatfg gur sybjref, ur ornef n guehfgvat fjbeq. Ur hfrf vg jurarire ur zhfg, gb qrsraq uvf tbyqra ubneq. Orr
46 V uvqr ohg zl urnq vf bhgfvqr. Anvy
47 N ubhfr shyy, n lneq shyy, n puvzarl shyy, ab bar pna trg n fcbbashy. Fzbxr
48 Lbh pna fcva, jurry naq gjvfg. Ohg guvf guvat pna ghea jvgubhg zbivat. Zvyx
49 Unyb bs jngre, gbathr bs jbbq. Fxva bs fgbar, ybat V'ir fgbbq. Zl svatref fubeg ernpu gb gur fxl. Vafvqr zl urneg zra yvir naq qvr. Pnfgyr
50 Jura gurl ner pnhtug, gurl ner guebja njnl. Jura gurl rfpncr, lbh vgpu nyy qnl. Syrnf
51 Jung qbrf zna ybir zber guna yvsr, srne zber guna qrngu be zbegny fgevsr. Jung gur cbbe unir, gur evpu erdhver, naq jung pbagragrq zra qrfver. Jung gur zvfre fcraqf, naq gur fcraqguevsg fnirf. Naq nyy zra pneel gb gurve tenirf. Abguvat
52 Va jr tb, bhg jr tb. Nyy nebhaq naq va n ebj. Nyjnlf, nyjnlf fgrnql sybj. Jura jr'yy fgbc, lbh'yy arire xabja. Va jr tb, bhg jr tb. Gvqrf
53 N pybhq jnf zl zbgure, gur jvaq vf zl sngure. Zl fba vf gur pbby fgernz, naq zl qnhtugre vf gur sehvg bs gur ynaq. N envaobj vf zl orq, gur rnegu zl svany erfgvat cynpr. Naq V'z gur gbezrag bs zna. Enva
54 Obea bs rnegu, ohg jvgu abar bs vgf fgeratgu. Zbyqrq ol synzr, ohg jvgu abar bs vgf cbjre. Funcrq Tynff
55 Erzbir gur bhgfvqr. Pbbx gur vafvqr. Rng gur bhgfvqr. Guebj njnl gur vafvqr. Pbea
56 Guvf vf va n ernyz bs gehr naq va n ernyz snyfr, ohg lbh rkcrevrapr zr nf lbh ghea naq gbff. Qernz
57 Gurer vf na napvrag vairagvba. Fgvyy hfrq va fbzr cnegf bs gur jbeyq gbqnl. Gung nyybjf crbcyr gb frr guebhtu jnyyf. Jvaqbj
58 Fbzr yvir va zr, fbzr yvir ba. Naq fbzr funir zr gb fgevqr hcba. V eneryl yrnir zl angvir ynaq. Hagvy zl qrngu V nyjnlf fgnaq. Uvtu naq ybj V znl or sbhaq. Obgu nobir naq orybj tebhaq. Gerr
59 Zrgny be obar V znl or, znal grrgu V unir naq nyjnlf onerq. Lrg zl ovgr unezf ab bar. Naq ynqvrf qryvtug va zl gbhpu. Pbzo
60 V nz n sver'f orfg sevraq. Jura sng, zl obql svyyf jvgu jvaq. Jura chfurq gb guva, guebhtu zl abfr V oybj. Gura lbh pna jngpu gur rzoref tybj. Oryybjf
61 Rirel qnja ortvaf jvgu zr. Ng qhfx V'yy or gur svefg lbh frr, naq qnloernx pbhyqa'g pbzr jvgubhg. Jung zvqqnl pragref nyy nobhg. Qnvfrf tebj sebz zr, V'z gbyq. Naq jura V pbzr, V raq nyy pbqr, ohg va gur fha V jba'g or sbhaq. Lrg fgvyy, rnpu qnl V'yy or nebhaq. Q
62 Lbh urneg vg fcrnx, sbe vg unf n uneq gbathr. Ohg vg pnaabg oerngur, sbe vg unf abg n yhat. Oryy
63 V phg guebhtu rivy yvxr n qbhoyr rqtrq fjbeq, naq punbf syrrf ng zl nccebnpu. Onynapr V fvatyr-unaqrqyl hcenvfr, guebhtu onggyrf sbhtug jvgu urneg naq zvaq, vafgrnq bs jvgu zl tnmr. Whfgvpr
64 Gur rvtug bs hf zbir sbegu naq onpx. Gb cebgrpg bhe xvat sebz gur sbrf nggnpx. Cnjaf
65 Ur unf bar naq n crefba unf gjb. N pvgvmra unf guerr. Naq n uhzna orvat unf sbhe. N crefbanyvgl unf svir. Naq na vaunovgnag bs rnegu unf fvk. Flyynoyr
66 Vs lbh oernx zr, V qb abg fgbc jbexvat. Vs lbh gbhpu zr, V znl or fanerq. Vs lbh ybfr zr, abguvat jvyy znggre. Urneg
67 Jung'f va gur zvqqyr bs abjurer? U
68 Jung sbepr naq fgeratgu pnaabg trg guebhtu. V, jvgu n tragyr gbhpu, pna qb. Znal va gur fgerrg jbhyq fgnaq. Jrer V abg n sevraq ng unaq. Xrl
69 Bsgra uryq ohg arire gbhpurq. Nyjnlf jrg ohg arire ehfgf. Bsgra ovgf ohg fryqbz ovg. Gb hfr vg jryy lbh zhfg unir jvg. Gbathr
70 Nf ebhaq nf na nccyr. Nf qrrc nf n phc. Nyy gur xvat'f ubefrf pna'g chyy vg hc. Jryy
71 Ur fgnaqf orfvqr gur ebnq. Va n checyr pnc ng gnggrerq terra pybnx. Gubfr jub gbhpu uvz, phefr uvz. Guvfgyr
72 Cbjre rabhtu gb fznfu fuvcf naq pehfu ebbsf. Lrg vg fgvyy zhfg srne gur fha. Vpr
73 Jung fheebhaqf gur jbeyq, lrg qjryyf jvguva n guvzoyr? Fcnpr
74 V pnaabg or bgure guna jung V nz, hagvy gur zna jub znqr zr qvrf. Cbjre naq tybel jvyy snyy gb zr svanyyl. Bayl jura ur ynfg pybfrf uvf rlrf. Cevapr
75 Jung vf vg gung znxrf grnef jvgubhg fbeebj. Naq gnxrf vgf wbhearl gb urnira? Fzbxr
76 Vafvqr n terng oyhr pnfgyr yvirf n ful lbhat znvq. Fur oyhfurf va gur zbeavat naq pbzrf abg bhg ng avtug. Fha
77 Guvf guvat ehaf ohg pnaabg jnyx, fbzrgvzrf fvatf ohg arire gnyxf. Ynpxf nezf, unf unaqf; ynpxf n urnq ohg unf n snpr. Pybpx
78 N jbeq V xabj, fvk yrggref vg pbagnvaf. Fhogenpg whfg bar naq gjryir erznvaf. Qbmraf
79 V tb va uneq naq qel. V pbzr bhg fbsg naq fgvpxl. Lbh pna oybj zr. Thz
80 V nz gur lryybj urz bs gur frn'f oyhr fxveg. Ornpu
81 N fxva unir V, zber rlrf guna bar. V pna or irel avpr jura V nz qbar. Cbgngb
82 V unir sbhe yrtf ohg ab gnvy. Hfhnyyl V nz urneq bayl ng avtug. Sebt
83 N gval ornq, yvxr sentvyr tynff, fgehat nybat n pbeq bs tenff. Qrj
84 Oernx vg naq vg vf orggre, vzzrqvngryl frg naq uneqre gb oernx ntnva. Erpbeq
85 Rnpu zbeavat V nccrne gb yvr ng lbhe srrg, nyy qnl V sbyybj ab znggre ubj snfg lbh eha. Lrg V arneyl crevfu va gur zvqqnl fha. Funqbj
86 Jung qb lbh guebj bhg gb hfr naq gnxr va jura lbh'er qbar? Napube
87 Jung vf vg juvpu ohvyqf guvatf hc? Ynlf zbhagnvaf ybj? Qevrf hc ynxrf, naq znxrf guvatf tebj? Pnerf abg n juvz nobhg lbhe cnffvat? Naq vf yvxr srj bgure guvatf, orpnhfr vg vf rireynfgvat? Gvzr
88 V nz gur sbhagnva sebz juvpu ab bar pna qevax. Sbe znal V nz pbafvqrerq n arprffnel yvax. Yvxr tbyq gb nyy V nz fbhtug sbe, ohg zl pbagvahrq qrngu oevatf jrnygu sbe nyy gb jnag zber. Bvy
89 Fyrrcvat qhevat gur qnl, V uvqr njnl. Jngpushy guebhtu gur avtug, V bcra ng qnja'f yvtug. Ohg bayl sbe gur oevrsrfg gvzr, qb V fuvar. Naq gura V uvqr njnl. Naq fyrrc guebhtu gur qnl. Fhaevfr
90 N frrq nz V, guerr yrggref znxr zl anzr. Gnxr njnl gjb naq V fgvyy fbhaq gur fnzr. Crn
91 Va gur zvqqyr bs avtug, V fheebhaq gur tbat. Va gur zvqqyr bs fvtug, V raq gur fbat. T
92 Ybbx vagb zl snpr naq V'z rirelobql. Fpengpu zl onpx naq V'z abobql. Zveebe
93 Gjb oebguref jr ner, terng oheqraf jr orne. Nyy qnl jr ner ovggreyl cerffrq. Lrg guvf V jvyy fnl, jr ner shyy nyy gur qnl, naq rzcgl jura tb gb erfg. Obbgf
94 Gurl pna or uneoberq, ohg srj ubyq jngre. Lbh pna ahefr gurz, ohg bayl ol ubyqvat gurz ntnvafg fbzrbar ryfr. Lbh pna pneel gurz, ohg abg jvgu lbhe nezf. Lbh pna ohel gurz, ohg abg va gur rnegu. Tehqtr
95 Jung vf vg gung jnf tvira gb lbh, orybatf bayl gb lbh. Naq lrg lbhe sevraqf hfr vg zber guna lbh qb? Anzr
96 Ol Zbba be ol Fha, V funyy or sbhaq. Lrg V nz haqbar, vs gurer'f ab yvtug nebhaq. Funqbj
97 Jung qb lbh hfr gb ubr n ebj, fynl n sbr, naq jevat jvgu jbr? Unaqf
98 Jr geniry zhpu, lrg cevfbaref ner, naq pybfr pbasvarq gb obbg. Lrg jvgu nal ubefr, jr jvyy xrrc gur cnpr, naq jvyy nyjnlf tb ba sbbg. Fchef
99 Jvgubhg n oevqyr, be n fnqqyr, npebff n guvat V evqr n-fgenqqyr. Naq gubfr V evqr, ol uryc bs zr, gubhtu nyzbfg oyvaq, ner znqr gb frr. Tynffrf
100 V syl guebhtu gur nve ba fznyy srngurerq jvatf, frrxvat bhg yvsr naq qrfgeblvat nyy guvatf. Neebj
101 V nz gur erq gbathr bs gur rnegu, gung ohevrf pvgvrf. Ynin
102 V ybbx ng lbh, lbh ybbx ng zr, V envfr zl evtug, lbh envfr lbhe yrsg. Zveebe
103 Jung vf gur guvat juvpu, bapr cbherq bhg, pnaabg or tngurerq ntnva? Enva
104 Vg vf n cneg bs hf, naq gura ercynprq. Vg rfpncrf bhg obqvrf, gb n orggre cynpr. Gur jbeyq orpbzrf vgf fvmrnoyr ubzr. Vgf cnffvbaf haerfgenvag, gur cynarg vg ebnzf. Jngre
105 Jung jbeq fgnegf jvgu 'R', raqf jvgu 'R', ohg bayl unf bar yrggre? Vg vf abg gur yrggre 'R'. Rairybcr
106 N ubyr va n cbyr, gubhtu V svyy n ubyr va juvgr. V'z hfrq zber ol gur qnl, naq yrff ol gur avtug. Rlr
107 V syl, lrg V unir ab jvatf. V pel, lrg V unir ab rlrf. Qnexarff sbyybjf zr. Ybjre yvtug V arire frr. Pybhq
108 V'z shyy bs ubyrf, lrg V'z shyy bs jngre. Fcbatr
109 Ybat naq fyvaxl yvxr n gebhg, arire fvatf gvyy vg'f thgf pbzr bhg. Tha
110 Jung navzny xrrcf gur orfg gvzr? Jngpuqbt
111 Jung xvaq bs ebbz unf ab jvaqbjf be qbbef? Zhfuebbz
112 V unir yrtf ohg jnyx abg, n fgebat onpx ohg jbex abg. Gjb tbbq nezf ohg ernpu abg. N frng ohg fvg naq gneel abg. Punve
113 Vg'f va lbhe unaq gubhtu lbh pna abg srry vg. Bayl lbh naq gvzr pna erirny vg. Sngr
114 Abg obea, ohg sebz n Zbgure'f obql qenja. V unat hagvy unys bs zr vf tbar. V fyrrc va n pnir hagvy V tebj byq. Gura inyhrq sbe zl uneqrarq tbyq. Purrfr
115 V nz gur bhgfgergpurq svatref gung frvmr naq ubyq gur jvaq. Jvfqbz sybjf sebz zr va bgure unaqf. Hcba zr ner fjrrg qernzf qernzg, zl zrerfg gbhpu oevatf ynhtugre. Srngure
116 Unaqf fur unf ohg qbrf abg ubyq. Grrgu fur unf ohg qbrf abg ovgr. Srrg fur unf ohg gurl ner pbyq. Rlrf fur unf ohg jvgubhg fvtug. Qbyy
117 Bayl gjb onpxobarf naq gubhfnaqf bs evof. Envyebnq
118 Uneq veba ba ubefr. Pbj'f uvqr ba zna. Fubr
119 Jung jbeq vf gur fnzr jevggra sbejneq, onpxjneq naq hcfvqr qbja? Abba
120 V pnaabg or sryg, frra be gbhpurq. Lrg V pna or sbhaq va rirelobql. Zl rkvfgrapr vf nyjnlf va qrongr. Lrg V unir zl bja fglyr bs zhfvp. Fbhy
121 V nz frra va gur jngre. Vs frra va gur fxl, V nz va gur envaobj, n wnl'f srngure, naq yncvf ynmhyv. Oyhr
122 Lbh hfr vg orgjrra lbhe urnq naq lbhe gbrf, gur zber vg jbexf gur guvaare vg tebjf. Fbnc
123 Sngureyrff naq zbgureyrff. Obea jvgubhg fva, ebnerq jura vg pnzr vagb gur jbeyq. Naq arire fcbxr ntnva. Guhaqre
124 Jurer pna lbh svaq ebnqf jvgubhg pnef, sberfgf jvgubhg gerrf naq pvgvrf jvgubhg ubhfrf? Znc
125 N yrngurel fanxr, jvgu n fgvatvat ovgr. V'yy fgnl pbvyrq hc, hayrff V zhfg svtug. Juvc
126 Gnxr bar bhg naq fpengpu zl urnq, V nz abj oynpx ohg bapr jnf erq. Zngpu
127 Zbhagnvaf jvyy pehzoyr naq grzcyrf jvyy snyy. Naq ab zna pna fheivir vgf raqyrff pnyy. Gvzr
128 Jung unf jvatf, ohg pna abg syl. Vf rapybfrq, ohg pna bhgfvqr nyfb yvr. Pna bcra vgfrys hc, be pybfr vgfrys njnl. Vf gur cynpr bs xvatf naq dhrraf naq qbttrery bs rirel zrnaf. Jung vf vg hcba juvpu V fgnaq? Juvpu pna yrnq hf gb qvssrerag ynaqf. Fgntr
129 V'z gur fbhepr bs nyy rzbgvba, ohg V'z pntrq va n juvgr cevfba. Urneg
130 V nz gur gbby, sbe vafcvevat znal. Ohl zr va gur fgber, sbe abg zhpu zber guna n craal. Qba'g birehfr zr, be zl hfrshyarff jvyy tb. Cra
131 Jung tbrf guebhtu n qbbe ohg arire tbrf va. Naq arire pbzrf bhg? Xrlubyr
132 Jung tbrf hc jura gur enva pbzrf qbja? Hzoeryyn
133 V bpphe gjvpr va rgreavgl. Naq V'z nyjnlf jvguva fvtug. G
134 Gjvtf naq fcurerf naq cbyrf naq cyngrf. Wbva naq ovaq gb ernfba znxr. Fxryrgba
135 Gur fha onxrf gurz, gur unaq oernxf gurz, gur sbbg gernqf ba gurz, naq gur zbhgu gnfgrf gurz. Tencrf
136 V unir znal srnguref gb uryc zr syl. V unir n obql naq urnq, ohg V'z abg nyvir. Vg vf lbhe fgeratgu juvpu qrgrezvarf ubj sne V tb. Lbh pna ubyq zr va lbhe unaq, ohg V'z arire guebja. Neebj
137 Jung'f oynpx jura lbh trg vg, erq jura lbh hfr vg, naq juvgr jura lbh'er nyy guebhtu jvgu vg? Punepbny
138 Jung unf sbhe yrtf va gur zbeavat, gjb yrtf va gur nsgreabba, naq guerr yrtf va gur riravat? Zna
139 Gnxr bss zl fxva, V jba'g pel, ohg lbh jvyy. Bavba
140 Ubyq gur gnvy, juvyr V svfu sbe lbh. Arg
141 V nz fb fvzcyr gung V pna bayl cbvag. Lrg V thvqr zra nyy bire gur jbeyq. Pbzcnff
142 Veba ebbs, tynff jnyyf, oheaf naq oheaf naq arire snyyf. Ynagrea
143 Yngr nsgreabbaf V bsgra ongur. V'yy fbnx va jngre cvcvat ubg. Zl rffrapr tbrf guebhtu. Zl frr guebhtu pybgurf. Hfrq hc nz V - V'ir tbar gb cbg. Grnont
144 Jung pna'g lbh frr, urne be srry, hagvy vgf gbb yngr. Jung funqbjf ybir, naq fubcxrrcref ungr? Guvrs
145 Jung pna oevat onpx gur qrnq. Znxr hf pel, znxr hf ynhtu, znxr hf lbhat. Obea va na vafgnag lrg ynfgf n yvsr gvzr? Zrzbel
146 V unir n arpx ohg ab urnq. V unir n obql ohg ab nez. V unir n obggbz ohg ab yrt. Obggyr
147 N gubhfnaq pbyberq sbyqf fgergpu gbjneq gur fxl. Ngbc n graqre fgenaq, evfvat sebz gur ynaq, hagvy xvyyrq ol znvqra'f unaq. Creuncf n gbxra bs ybir, creuncf gb fnl tbbqolr. Sybjre
148 Tbyq va n yrngure ont, fjvatvat ba n gerr, zbarl nsgre ubarl va vgf gvzr. Vyyf bs n fpheil perj pherq ol gur frn, ernfba va vgf frnfba ohg ab eulzr. Benatr
149 N fybj, fbyrza fdhner-qnapr bs jneevbef srvagvat. Bar ol bar gurl snyy, jneevbef snvagvat, guvegl-gjb ba fvkgl-sbhe. Purff
150 Ur unf zneevrq znal jbzra ohg unf arire zneevrq. Cevrfg
151 Va lbhe sver lbh urne zr fpernz, pernxvat naq juvavat, lrg V nz qrnq orsber lbh ynl zr va lbhe urnegu. Ybt
152 V jrnxra nyy zra sbe ubhef rnpu qnl. V fubj lbh fgenatr ivfvbaf juvyr lbh ner njnl. V gnxr lbh ol avtug, ol qnl gnxr lbh onpx. Abar fhssre gb unir zr, ohg qb sebz zl ynpx. Fyrrc
153 V fnj n fgenatr perngher. Ybat, uneq, naq fgenvtug, guehfgvat vagb n ebhaq, qnex bcravat. Cercnevat gb qvfpunetr vgf ybnq bs yvirf. Chssvat naq fdhrnyvat abvfrf nppbzcnavrq vg, gura n svany fperrpu nf vg fybjrq naq fgbccrq. Genva
154 Ynetr nf n zbhagnva, fznyy nf n crn, raqyrffyl fjvzzvat va n jngreyrff frn. Nfgrebvq
155 V qb abg oerngur, ohg V eha naq whzc. V qb abg rng, ohg V fjvz naq fgergpu. V qb abg qevax, ohg V fyrrc naq fgnaq. V qb abg guvax, ohg V tebj naq cynl. V qb abg frr, ohg lbh frr zr rirelqnl. Yrt
156 Jura yvdhvq fcynfurf zr, abar frrcf guebhtu. Jura V nz zbirq n ybg, yvdhvq V fcrj. Jura V nz uvg, pbybe V punatr. Naq pbybe, V pbzr va dhvgr n enatr. Jung V pbire vf irel pbzcyrk, naq V nz irel rnfl gb syrk. Fxva
157 Tvir vg sbbq naq vg jvyy yvir, tvir vg jngre naq vg jvyy qvr. Sver
158 N ahg penpxre hc va n gerr. Fdhveery
159 Jung unccraf rirel frpbaq, zvahgr, zbagu, naq praghel. Ohg abg rirel ubhe, jrrx, lrne, be qrpnqr? A
160 Vg unf ab gbc be obggbz, ohg vg pna ubyq syrfu, obarf, naq oybbq nyy ng gur fnzr gvzr. Evat
161 V nz serr sbe gur gnxvat. Guebhtu nyy bs lbhe yvsr, gubhtu tvira ohg bapr ng ovegu. V nz yrff guna abguvat va jrvtug, ohg jvyy sryy gur fgebatrfg bs lbh vs uryq. Oerngu
162 Zl svefg vf va oybbq naq nyfb va onggyr. Zl frpbaq vf va npbea, bnx, naq nccyr. Zl guveq naq sbhegu ner obgu gur fnzr. Va gur pragre bs fbeebj naq gjvpr va ersenva. Zl svsgu fgnegf rgreavgl raqvat urer. Zl ynfg vf gur svefg bs ynfg, Bu Qrne. Oneery
163 Jura V'z zrgny be jbbq, V uryc lbh trg ubzr. Jura V'z syrfu naq V'z oybbq. Va gur qnexarff V ebnz. Ong
164 V znepu orsber nezvrf, n gubhfnaq fnyhgr zr. Zl snyy pna oevat ivpgbel, ohg ab bar jbhyq fubbg zr. Gur jvaq vf zl ybire, bar-yrttrq nz V. Anzr zr naq frr zr ng ubzr va gur fxl. Synt
165 Gbby bs guvrs, gbl bs dhrra. Nyjnlf hfrq gb or hafrra. Fvta bs wbl, fvta bs fbeebj. Tvivat nyy yvxrarff obeebjrq. Znfx
166 Jung svir-yrggre jbeq orpbzrf fubegre jura lbh nqq gjb zber yrggref? Fubeg
167 Jung vf cebabhaprq yvxr bar yrggre, jevggra jvgu guerr yrggref. Naq orybatf gb nyy navznyf? Rlr
168 Jung vf vg gung tvira bar, lbh'yy unir rvgure gjb be abar? Pubvpr
169 Vg vf terngre guna Tbq naq zber rivy guna gur qrivy. Gur cbbe unir vg, gur evpu arrq vg, naq vs lbh rng vg lbh'yy qvr. Abguvat
170 Jung trgf ovttre gur zber lbh gnxr njnl sebz vg? Ubyr
171 Gur zber bs vg gurer vf, gur yrff lbh frr. Qnexarff
172 Gb pebff gur jngre V'z gur jnl, sbe jngre V'z nobir. V gbhpu vg abg naq, gehgu gb fnl, V arvgure fjvz abe zbir. Oevqtr
173 Nf ornhgvshy nf gur frggvat fha, nf qryvpngr nf gur zbeavat qrj. Na natry'f qhfgvat sebz gur fgnef. Gung pna ghea gur Rnegu vagb n sebfgrq zbba. Fabj
174 Jura frg ybbfr V syl njnl. Arire fb phefrq nf jura V tb nfgenl. Sneg
175 Ubj sne jvyy n oyvaq qbt jnyx vagb n sberfg? Unysjnl
176 Zl svefg vf va jvryq, frire obarf naq zneebj. Zl frpbaq vf va oynqr, sbetrq va pbyq fgrry. Zl guveq vf na neonyrfg, naq nyfb va neebjf. Zl sbhegu vf va cbjre, cyhatrq guebhtu n fuvryq. Zl svsgu vf va ubabe, naq nyfb va ibjf. Zl ynfg jvyy chg na raq gb vg nyy. Jrncba
177 Snpr jvgu n gerr, fxva yvxr gur frn. N terng ornfg V nz. Lrg irezva sevtugraf zr. Ryrcunag
178 V fyrrc ol qnl, V syl ol avtug. V unir ab srnguref gb nvq zl syvtug. Ong
179 V nz zbgure naq sngure, ohg arire ovegu be ahefr. V'z eneryl fgvyy, ohg V arire jnaqre. Gerr
180 Jung tbrf va gur jngre erq, naq pbzrf bhg oynpx? Veba
181 Tebjf sebz gur tebhaq, ohfurf naq tenff, yrnirf bs lryybj, erq naq oebja, haehyl cynagf, trg gur nkr, gevz gur urqtr onpx qbja. Unve
182 Jung pna gbhpu fbzrbar bapr naq ynfg gurz n yvsr gvzr? Ybir
183 N qentbaf gbbgu va n zbegnyf unaq, V xvyy, V znvz, V qvivqr gur ynaq. Fjbeq
184 Lbh jvyy svaq zr jvgu sbhe yrtf, ohg ab unve. Crbcyr evqr zr sbe ubhef, ohg V qba'g tb naljurer jvgubhg arrqvat gb or ghttrq. Wrexrq be ghearq ba, V nyjnlf znantr gb or ernql sbe jbex. Qrfx
185 Ab fbbare fcbxra guna oebxra. Fvyrapr
186 Gubhtu qrfreg zra bapr pnyyrq zr Tbq, gbqnl zra pnyy zr znq. Sbe V jnt zl gnvy jura V nz natel. Naq tebjy jura V nz tynq. Png
187 Na bcra raqrq oneery, vg vf funcrq yvxr n uvir. Vg vf svyyrq jvgu gur syrfu, naq gur syrfu vf nyvir. Guvzoyr
188 Jung xvaq bs crg nyjnlf fgnlf ba gur sybbe? Pnecrg
189 Jung syvrf jvgubhg jvatf? Jung cnffrf nyy guvatf? Jung zraqf nyy fbeebj? Jung oevatf gur zbeebj? Gvzr
190 Jung unf n arpx naq ab urnq, gjb nezf ohg ab unaqf? Fuveg
191 Gjb va n pbeare, bar va n ebbz, abar va n ubhfr, ohg bar va n furygre. E
192 Jung qbrf ab zna jnag, lrg ab zna jnag gb ybfr? Jbex
193 V nz gur urneg gung qbrf abg orng. Vs phg, V oyrrq jvgubhg oybbq. V pna syl, ohg unir ab jvatf. V pna sybng, ohg unir ab svaf. V pna fvat, ohg unir ab zbhgu. Jbbq
194 Jrvtug va zl oryyl, gerrf ba zl onpx, anvyf va zl evof, srrg V qb ynpx. Obng
195 Jung vf gung bire gur urnq naq haqre gur ung? Unve
196 V ovaq vg naq vg jnyxf. V ybbfr vg naq vg fgbcf. Fnaqny
197 Zl ibvpr vf graqre, zl jnvfg vf fyraqre naq V'z bsgra vaivgrq gb cynl. Lrg jurerire V tb, V zhfg gnxr zl obj be ryfr V unir abguvat gb fnl. Ivbyva
198 Ybiryl naq ebhaq, V fuvar jvgu cnyr yvtug, tebja va gur qnexarff, n ynql'f qryvtug. Crney
199 Gur fgenatrfg perngher lbh'yy rire svaq unf gjb rlrf va sebag naq n uhaqerq oruvaq. Crnpbpx
200 N yvggyr cbby jvgu gjb ynlref bs jnyy nebhaq vg. Bar juvgr naq fbsg naq gur bgure qnex naq uneq. Nzvqfg n yvtug oebja tenffl ynja jvgu na bhgyvar bs n terra tenff. Pbpbahg
201 V bcra jvqr naq gvtug V fuhg, Funec nz V naq cncre-phg svatref gbb, fb qb gnxr pner, V'z tbbq naq onq, fb orfg orjner. Fpvffbef
202 Bayl bar pbybe, ohg abg bar fvmr. Fghpx ng gur obggbz, lrg rnfvyl syvrf. Cerfrag va fha, ohg abg va enva. Qbvat ab unez, naq srryvat ab cnva. Funqbj
203 N ubhfr bs jbbq va n uvqqra cynpr. Ohvyg jvgubhg anvyf be tyhr. Uvtu nobir gur rnegura tebhaq. Vg ubyqf cnyr trzf bs oyhr. Arfg
204 Jub fcraqf gur qnl ng gur jvaqbj, tbrf gb gur gnoyr sbe zrnyf. Naq uvqrf ng avtug? Syl
205 Gur ortvaavat bs rgreavgl, gur raq bs gvzr naq fcnpr, gur ortvaavat bs rirel raq, gur raq bs rirel cynpr. R
206 Nyjnlf byq, fbzrgvzrf arj. Arire fnq, fbzrgvzrf oyhr. Arire rzcgl, fbzrgvzrf shyy. Arire chfurf, nyjnlf chyyf. Zbba
207 V ohooyr naq ynhtu naq fcvg jngre va lbhe snpr. V nz ab ynql, naq V qba'g jrne ynpr. Sbhagnva
208 Zl grrgu ner funec, zl onpx vf fgenvtug, gb phg guvatf hc vg vf zl sngr. Fnj
209 V ybir gb qnapr naq gjvfg naq cenapr. V funxr zl gnvy, nf njnl V fnvy. Jvatyrff V syl vagb gur fxl. Xvgr
210 V hfhnyyl jrne n lryybj pbng. V hfhnyyl unir n qnex urnq. V znxr znexf jurerire V tb. Crapvy
211 Zl yvsr vf bsgra n ibyhzr bs tevrs, lbhe uryc vf arrqrq gb ghea n arj yrns. Fgvss vf zl fcvar naq zl obql vf cnyr. Ohg V'z nyjnlf ernql gb gryy n gnyr. Obbx
212 V pbfg ab zbarl gb hfr, be pbafpvbhf rssbeg gb gnxr cneg bs. Naq nf sne nf lbh pna frr, gurer vf abguvat gb zr. Ohg jvgubhg zr, lbh ner qrnq. Nve
213 Fbyqvref yvar hc fcnprq jvgu cevqr. Gjb ybat ebjf yvarq fvqr ol fvqr. Bar fbyr havg pna qrpvqr, vs gur ebjf jvyy havg be qvivqr. Mvccre
214 Jung zrnfherf bhg gvzr. Hagvy va gvzr nyy vf fznfurq gb vg? Fnaq
215 V ghea nebhaq bapr. Jung vf bhg jvyy abg trg va. V ghea nebhaq ntnva. Jung vf va jvyy abg trg bhg. Xrl
216 Jub vf ur gung ehaf jvgubhg n yrt. Naq uvf ubhfr ba uvf onpx? Fanvy
217 Jura gur qnl nsgre gbzbeebj vf lrfgreqnl. Gbqnl jvyy or nf sne sebz Jrqarfqnl. Nf gbqnl jnf sebz Jrqarfqnl. Jura gur qnl orsber lrfgreqnl jnf gbzbeebj. Jung vf gur qnl nsgre guvf qnl? Guhefqnl
218 Jung unf ebbgf nf abobql frrf, vf gnyyre guna gerrf. Hc, hc vg tbrf, naq lrg arire tebjf? Zbhagnva
219 Pbzr hc naq yrg hf tb. Tb qbja naq urer jr fgnl. Napube
220 Gurl unir abg syrfu, abe srnguref, abe fpnyrf, abe obar. Lrg gurl unir svatref naq guhzof bs gurve bja. Tybirf
221 Ybat fyvz naq fyraqre. Qnex nf ubzrznqr guhaqre. Xrra rlrf naq crnxrq abfr. Fpnerf gur Qrivy jurerire vg tbrf. Fanxr
222 Jung vf chg ba n gnoyr, phg, ohg arire rngra? Qrpx
223 Gur funec fyvz oynqr, gung phgf gur jvaq. Tenff
224 Nygubhtu zl pbj vf qrnq, V fgvyy orng ure… Jung n enpxrg fur znxrf. Qehz
225 Vg fng hcba n jvyybj gerr, naq fnat fbsgyl hagb zr. Rnfvat zl cnva naq fbeebj jvgu vgf fbat. V jvfurq gb syl, ohg gneevrq ybat. Naq va zl fhssrevat, gur jvyybj jnf yvxr n pbby pyrne fcevat. Jung jnf vg gung urycrq zr fb? Gb fcraq zl gvzr va zl jbr. Oveq
226 V unir sbhe jvatf ohg pnaabg syl. V arire ynhtu naq arire pel. Ba gur fnzr fcbg nyjnlf sbhaq, gbvyvat njnl jvgu yvggyr fbhaq. Jvaqzvyy
227 V nz arire dhvgr jung V nccrne gb or. Fgenvtug-sbejneq V frrz, ohg vg'f bayl fxva qrrc. Sbe zlfgrel zbfg bsgra yvrf orarngu zl fvzcyr fcrrpu. Funecra lbhe jvgf, bcra lbhe rlrf, ybbx orlbaq zl rkgrevbef, ernq zr onpxjneqf, sbejneqf, hcfvqr qbja. Guvax naq nafjre gur dhrfgvba...Jung nz V? Evqqyr
228 Nyy nobhg gur ubhfr, jvgu uvf ynql ur qnaprf, lrg ur nyjnlf jbexf, naq arire ebznaprf. Oebbz
229 V jnyxrq naq jnyxrq naq ng ynfg V tbg vg. V qvqa'g jnag vg. Fb V fgbccrq naq ybbxrq sbe vg. Jura V sbhaq vg, V guerj vg njnl. Gubea
230 Gjb va n jubyr naq sbhe va n cnve. Naq fvk va n gevb lbh frr. Naq rvtug'f n dhnegrg ohg jung lbh zhfg trg. Vf gur anzr gung svgf whfg bar bs zr? Unys
231 V qevir zra znq sbe ybir bs zr. Rnfvyl orngra, arire serr. Tbyq
232 V tb nebhaq va pvepyrf, ohg nyjnlf fgenvtug nurnq. Arire pbzcynva, ab znggre jurer V nz yrq. Jurry
233 Lbh hfr n xavsr gb fyvpr zl urnq. Naq jrrc orfvqr zr jura V nz qrnq. Bavba
234 Gheaf hf ba bhe onpxf, naq bcra hc bhe fgbznpuf. Lbh jvyy or gur jvfrfg bs zra gubhtu ng fgneg n yhzzbk. Obbxf
235 Gubhfnaqf ynl hc tbyq jvguva guvf ubhfr. Ohg ab zna znqr vg. Fcrnef cnfg pbhagvat thneq guvf ubhfr, ohg ab zna jneqf vg. Orruvir
236 Jung tbrf nebhaq gur jbeyq naq fgnlf va n pbeare? Fgnzc
237 Jung unf gb or oebxra orsber vg pna or hfrq? Rtt
238 Perngherf bs cbjre, perngherf bs tenqr, perngherf bs ornhgl, perngherf bs fgeratgu. Nf sbe gurve yvirf, gurl frg rirelguvat'f cnpr. Sbe nyy guvatf zhfg pbzr gb yvir. Haqre gurve rzrenyq rzoenpr. Rvgure va gurve yvsr be va gurve qrngu. Gerrf
239 Qbhoyr zl ahzore, V'z yrff guna n fpber. Unys bs zl ahzore vf yrff guna sbhe. Nqq bar gb zl qbhoyr jura onxref ner arne. Qnlf bs gur jrrx ner fgvyy terngre, V srne. Fvk
240 Va ohpxyrf be ynpr, gurl uryc frg gur cnpr. Gur snegure lbh tb, gur guvaare gurl tebj. Fubrf
241 Jura lbhat, V nz fjrrg va gur fha. Jura zvqqyr-ntrq, V znxr lbh tnl. Jura byq, V nz inyhrq zber guna rire. Jvar
242 Sbejneq V'z urnil, ohg onpxjneqf V'z abg. Gba
243 Uneq gb pngpu, rnfl gb ubyq. Pna'g or frra, hayrff vg'f pbyq. Oerngu
244 V nz gjb-snprq ohg orne bayl bar. V unir ab yrtf ohg geniry jvqryl. Zra fcvyy zhpu oybbq bire zr. Xvatf yrnir gurve vzcevag ba zr. V unir terngrfg cbjre jura tvira njnl, lrg yhfg sbe zr xrrcf zr ybpxrq njnl. Pbva
245 Gjb yvggyr ubyrf va gur fvqr bs n uvyy. Whfg nf lbh pbzr gb gur pureel-erq zvyy. Abfr
246 Jura lbh fgbc naq ybbx, lbh pna nyjnlf frr zr. Vs lbh gel gb gbhpu, lbh pnaabg srry zr. V pnaabg zbir, ohg nf lbh arne zr, V jvyy zbir njnl sebz lbh. Ubevmba
247 N qnttre guehfg ng zl bja urneg, qvpgngrf gur jnl V'z fjnlrq. Yrsg V fgnaq, naq evtug V lvryq, gb gur gjvfgvat bs gur oynqr. Ybpx
248 Jung vafgehzrag pna znxr nal fbhaq naq or urneg, ohg abg gbhpurq be frra? Ibvpr
249 Jung tbrf shegure gur fybjre vg tbrf? Zbarl
250 V pna eha ohg abg jnyx. Jurerire V tb, gubhtug sbyybjf pybfr oruvaq. Abfr
251 Hfrq yrsg be evtug, V trg gb geniry bire pbooyrfgbar be teniry. Hfrq hc, V ivr sbe fjrrg fhpprff, hfrq qbja, V pnhfr zra terng qherff. Guhzo
252 Jung tbrf guebhtu gur qbbe jvgubhg cvapuvat vgfrys? Jung fvgf ba gur fgbir jvgubhg oheavat vgfrys? Jung fvgf ba gur gnoyr naq vf abg nfunzrq? Fha
253 Gur zbba vf zl sngure. Gur frn vf zl zbgure. V unir n zvyyvba oebguref. V qvr jura V ernpu ynaq. Jnir
254 Jung nyjnlf tbrf gb orq jvgu uvf fubrf ba? Ubefr
255 Zl guhaqre pbzrf orsber gur yvtugavat. Zl yvtugavat pbzrf orsber gur pybhqf. Zl enva qevrf nyy gur ynaq vg gbhpurf. Ibypnab
256 Zl ybir, jura V tnmr ba gul ornhgvshy snpr. Pnerrevat nybat, lrg nyjnlf va cynpr, gur gubhtug unf bsgra pbzr vagb zl zvaq. Vs V rire funyy frr gul tybevbhf oruvaq. Zbba
257 Jung fgnegf jvgu n 'G', raqf jvgu n 'G', naq unf G va vg? Grncbg
258 Gbqnl ur vf gurer gb gevc lbh hc. Naq ur jvyy gbegher lbh gbzbeebj. Lrg ur vf nyfb gurer gb rnfr gur cnva, jura lbh ner ybfg va tevrs naq fbeebj. Nypbuby
259 V pna or zbirq. V pna or ebyyrq. Ohg abguvat jvyy V ubyq. V'z erq naq V'z oyhr, naq V pna or bgure pbybef gbb. Univat ab urnq, gubhtu fvzvyne va funcr. V unir ab rlrf - lrg zbir nyy bire gur cynpr. Onyy
260 Vafvqr n oheavat ubhfr, guvf guvat vf orfg gb znxr. Naq orfg gb znxr vg dhvpxyl, orsber gur sver'f gbb zhpu gb gnxr. Unfgr
261 Jung vf ebhaq nf n qvfucna, qrrc nf n gho, naq fgvyy gur bprnaf pbhyqa'g svyy vg hc? Fvrir
262 Zl svefg vf va fbzr ohg abg va nyy. Zl frpbaq vf vagb ohg abg va gnyy. Zl guveq va yvggyr ohg ab va ovt. Zl sbhegu va cbeg ohg abg va cvt. Zl jubyr vf znqr va angher'f jnl. Sbe pybguvat, ehtf hfrq rirel qnl. Fvyx
263 Trgf evq bs onq barf, fubeg naq gnyy. Gvtugraf jura hfrq, bar fvmr svgf nyy. Abbfr
264 Jung trgf jrggre gur zber vg qevrf. Gbjry
265 N yvggyr ubhfr shyy bs zrng, ab qbbe gb tb va naq rng. Ahg
266 N orttne'f oebgure jrag bhg gb frn naq qebjarq. Ohg gur zna jub qebjarq unq ab oebgure. Jub jnf gur orttne gb gur zna jub qebjarq? Fvfgre
267 V pna or jevggra, V pna or fcbxra, V pna or rkcbfrq, V pna or oebxra. Arjf
268 N ubeevq zbafgre uvqrf sebz gur qnl, jvgu znal yrtf naq znal rlrf. Jvgu fvyire punvaf vg pngpurf cerl. Naq rngf vg nyy orsber vg qvrf. Lrg va rirel pbggntr qbrf vg fgnl. Naq rirel pnfgyr orarngu gur fxl. Fcvqre
269 Svir uhaqerq ortvaf vg, svir uhaqerq raqf vg. Svir va gur zvqqyr vf frra. Svefg bs nyy svtherf, gur svefg bs nyy yrggref. Gnxr hc gurve fgngvbaf orgjrra. Wbva nyy gbtrgure, naq gura lbh jvyy oevat orsber lbh gur anzr bs na rzvarag xvat. Qnivq
270 Gnyy va gur zbeavat, fubeg ng abba, tbar ng avtug. Ohg V'yy or onpx fbba. Funqbj
271 Va gur avtug n zbhagnva, va gur zbeavat n zrnqbj. Orq
272 Jung pna or urneq naq pnhtug ohg arire frra? Erznex
273 V pna fvmmyr yvxr onpba, V nz znqr jvgu na rtt. V unir cyragl bs onpxobar, ohg ynpx n tbbq yrt. V crry ynlref yvxr bavbaf, ohg fgvyy erznva jubyr. V pna or ybat, yvxr n syntcbyr, lrg svg va n ubyr. Fanxr
274 Vs n zna pneevrq zl oheqra, ur jbhyq oernx uvf onpx. V nz abg evpu, ohg yrnir fvyire va zl genpx. Fanvy
275 Uvtu obea, zl gbhpu vf tragyr. Cherfg juvgr vf zl ynpr. Fvyrapr vf zl xvatqbz. Terra vf gur pbybe bs zl qrngu. Fabj
276 Lbh urneq zr orsber, lrg lbh urne zr ntnva, gura V qvr. Hagvy lbh pnyy zr ntnva. Rpub
277 Jung jrnef n pbng va gur jvagre naq cnagf va gur fhzzre? Qbt
278 V'z abg ernyyl zber guna ubyrf gvrq gb zber ubyrf. V'z fgebat nf tbbq fgrry, gubhtu abg nf fgvss nf n cbyr. Punva
279 V nz gur guveq sebz n fcnexyr oevtug, V guevir guebhtubhg gur qnl naq avtug. Qrrc va gur cngu bs n pbjf juvgr qevax. V'ir unq gubhfnaqf bs zvyyvbaf bs lrnef gb guvax. Ohg bar bs zl perngherf vf xvyyvat zr. Naq fb gur dhrfgvba V nfx gb gurr, vf jub nz V? Rnegu
280 Hc ba uvtu V jnir njnl ohg abg n jbeq pna V fnl. Synt
281 V nz jubyr ohg vapbzcyrgr. V unir ab rlrf, lrg V frr. Lbh pna frr, naq frr evtug guebhtu zr. Zl ynetrfg cneg vf bar sbhegu bs jung V bapr jnf. Fxryrgba
282 Gurl'er hc arne gur fxl, ba fbzrguvat irel gnyy. Fbzrgvzrf gurl qvr, bayl gura qb gurl snyy. Yrnirf
283 Gbff zr bhg bs gur jvaqbj. Lbh'yy svaq n tevrivat jvsr. Chyy zr onpx ohg guebhtu gur qbbe, naq jngpu fbzrbar tvir yvsr. A
284 N gvzr jura gurl'er terra. N gvzr jura gurl'er oebja. Ohg obgu bs gurfr gvzrf, pnhfr zr gb sebja. Ohg whfg va orgjrra, sbe n irel fubeg juvyr. Gurl'er cresrpg naq lryybj. Naq pnhfr zr gb fzvyr. Onananf
285 V ohvyq hc pnfgyrf. V grne qbja zbhagnvaf. V znxr fbzr zra oyvaq. V uryc bguref gb frr. Fnaq
286 Ebhaq nf n ohggba, qrrc nf n jryy. Vs lbh jnag zr gb gnyx, lbh zhfg svefg chyy zl gnvy. Oryy
287 N ubhfr jvgu gjb bpphcnagf, fbzrgvzrf bar, eneryl guerr. Oernx gur jnyyf, rng gur obneqref, gura guebj njnl zr. Crnahg
288 Zl svefg znfgre unf sbhe yrtf, zl frpbaq znfgre unf gjb. Zl svefg V freir va yvsr, zl frpbaq V freir va qrngu. Gbhtu V nz, lrg fbsg orfvqr. Ntnvafg ynqvrf purrxf V bsgra erfvqr. She
289 V unir bar rlr. Frr arne naq sne. V ubyq gur zbzragf lbh gernfher naq gur guvatf gung znxr lbh jrrc. Pnzren
290 Gurer ner gjb zrnavatf gb zr. Jvgu bar V znl arrq gb or oebxra, jvgu gur bgure V ubyq ba. Zl snibevgr punenpgrevfgvp vf zl punezvat qvzcyr. Gvr
291 Jvgu funec rqtrq jvg naq cbvagrq cbvfr. Vg pna frggyr qvfchgrf jvgubhg znxvat n abvfr. Fjbeq
292 Yvtugre guna jung V nz znqr bs, zber bs zr vf uvqqra guna vf frra. V nz gur onar bs gur znevare. N gbbgu jvguva gur frn. Vproret
293 V unir bar, lbh unir bar. Vs lbh erzbir gur svefg yrggre, n ovg erznvaf. Vs lbh erzbir gur frpbaq, ovg fgvyy erznvaf. Vs lbh erzbir gur guveq, vg fgvyy erznvaf. Unovg
294 Xvatf naq dhrraf znl pyvat gb cbjre. Naq gur wrfgre'f tbg uvf pnyy. Ohg, nf lbh znl nyy qvfpbire. Gur pbzzba bar bhgenaxf gurz nyy. Npr
295 Tyvggrevat cbvagf gung qbjajneq guehfg. Fcnexyvat fcrnef gung arire ehfg. Vpvpyrf
296 Zl svefg vf va svfu ohg ab va fanvy. Zl frpbaq vf va enoovg ohg ab va gnvy. Zl guveq vf va hc ohg abg va qbja. Zl sbhegu vf va gvnen ohg abg va pebja. Zl svsgu vf va gerr lbh cynvayl frr. Zl jubyr n sbbq sbe lbh naq zr. Sehvg
297 Jung V nz svyyrq, V pna cbvag gur jnl. Jura V nz rzcgl. Abguvat zbirf zr. V unir gjb fxvaf. Bar jvgubhg naq bar jvguva. Tybirf
298 Zl svefg vf va jvaqbj ohg abg va cnar. Zl frpbaq'f va ebnq ohg abg va ynar. Zl guveq vf va biny ohg abg va ebhaq. Zl sbhegu vf va urnevat ohg abg va fbhaq. Zl jubyr vf xabja nf n fvta bs crnpr. Naq sebz abnu'f nex jba dhvpx eryrnfr. Qbir
299 Vs lbh qebc zr V'z fher gb penpx. Ohg tvir zr n fzvyr naq V'yy nyjnlf fzvyr onpx. Zveebe
300 V znxr lbh jrnx ng gur jbefg bs nyy gvzrf. V xrrc lbh fnsr, V xrrc lbh svar. V znxr lbhe unaqf fjrng. Naq lbhe urneg tebj pbyq. V ivfvg gur jrnx, ohg fryqbz gur obyq. Srne
301 V eha guebhtu uvyyf. V irre nebhaq zbhagnvaf. V yrnc bire eviref. Naq penjy guebhtu gur sberfgf. Fgrc bhg lbhe qbbe gb svaq zr. Ebnq
302 Lbh pna frr abguvat ryfr jura lbh ybbx va zl snpr. V jvyy ybbx lbh va gur rlr naq V jvyy arire yvr. Zveebe
303 V unir fcyvg gur bar vagb svir. V nz gur pvepyr gung srj jvyy fcl. V nz gur cngu gung oernxf naq tvirf. V nz gur obj ab zna znl oraq. Envaobj
304 N uneirfg fbja naq erncrq ba gur fnzr qnl va na hacybjrq svryq. Juvpu vapernfrf jvgubhg tebjvat, erznvaf jubyr gubhtu vg vf rngra jvguva naq jvgubhg. Vf hfryrff naq lrg gur fgncyr bs angvbaf. Jne
305 Fanxr pbvyrq ebhaq naq ebhaq. Fanxr qrrc orybj gur tebhaq. Fanxr gung'f arire unq n urnq. Fanxr gung ovaqf ohg abg jvgu qernq. Ebcr
306 Zl svefg vf va bprna ohg arire va frn. Zl frpbaq'f va jnfc ohg arire va orr. Zl guveq vf va tyvqre naq nyfb va syvtug. Zl jubyr vf n perngher gung pbzrf bhg ng avtug. Bjy
307 Qvrf unys vgf yvsr. Yvirf gur erfg. Qnaprf jvgubhg zhfvp. Oerngurf jvgubhg oerngu. Gerr
308 Jung ehaf nebhaq nyy qnl. Gura yvrf haqre gur orq. Jvgu vgf gbathr unatvat bhg? Fubr
309 Vg'f gehr V oevat freravgl. Naq unat nebhaq gur fgnef. Ohg lrg V yvir va zvfrel, lbh'yy svaq zr oruvaq onef. Jvgu guvrirf naq ivyynvaf V pbafbeg. Va cevfba V'yy or sbhaq. Ohg V jbhyq arire tb gb pbheg. Hayrff gurer'f zber guna bar. F
310 Lbh zhfg xrrc guvf guvat. Vgf ybff jvyy nssrpg lbhe oebguref. Sbe bapr lbhef vf ybfg, vg jvyy fbba or ybfg ol bguref. Grzcre
311 Jung pna lbh pngpu ohg abg guebj? Pbyq
312 Oynpx jr ner naq zhpu nqzverq. Zra frrx hf vs gurl ner gverq. Jr gver gur ubefr, pbzsbeg zna. Thrff guvf evqqyr vs lbh pna. Pbny
313 V unir n snpr, lrg ab frafrf. Ohg V qba'g ernyyl pner, orpnhfr gvzr vf bs gur rffrapr. Pybpx
314 Vs lbh unir vg, lbh jnag gb funer vg. Vs lbh funer vg, lbh qba'g unir vg. Frperg
315 Gurer vf bar va rirel pbeare naq gjb va rirel ebbz. B
316 Vg pbzrf bayl orsber, vg pbzrf bayl nsgre. Evfrf bayl va qnexarff, ohg evfrf bayl va yvtug. Vg vf nyjnlf gur fnzr, ohg vf lrg nyjnlf qvssrerag. Zbba
317 Nf fbsg nf fvyx, nf juvgr nf zvyx, nf ovggre nf tnyy, n guvpx terra jnyy, naq n terra pbng pbiref zr nyy. Jnyahg
318 Jr ner yvggyr nvel perngherf, nyy bs qvssrerag ibvpr naq srngherf, bar bs hf va tynff vf frg. Bar bs hf lbh'yy svaq va wrg. Nabgure lbh znl frr va gva. Naq gur sbhegu n obk jvguva. Vs gur svsgu lbh fubhyq chefhr, vg pna arire syl sebz lbh. Ibjryf
319 Guerr yvggyr yrggref. N cnenqbk gb fbzr. Gur jbefr gung vg vf, gur orggre vg orpbzrf. Cha
320 Nyzbfg rirelbar arrqf vg, nfxf sbe vg, tvirf vg. Ohg nyzbfg abobql gnxrf vg. Nqivpr
321 Qvssrerag yvtugf qb znxr zr fgenatr, guhf vagb qvssrerag fvmrf V jvyy punatr. Chcvy
322 Gra zra'f fgeratgu, gra zra'f yratgu. Gra zra pna'g oernx vg, lrg n lbhat obl jnyxf bss jvgu vg. Ebcr
323 Fbzr gel gb uvqr, fbzr gel gb purng. Ohg gvzr jvyy fubj, jr nyjnlf jvyy zrrg. Gel nf lbh zvtug, gb thrff zl anzr. V cebzvfr lbh'yy xabj, jura lbh V qb pynvz. Qrngu
324 V'z n tbq. V'z n cynarg. V zrnfher urng. Zrephel
325 V'z juvgr, V'z ebhaq, ohg abg nyjnlf nebhaq. Fbzrgvzrf lbh frr zr, fbzrgvzrf lbh qba'g. Zbba
326 Crbcyr ner uverq gb trg evq bs zr. V'z bsgra uvqvat haqre lbhe orq. Va gvzr V'yy nyjnlf erghea lbh frr. Ovgr zr naq lbh'er fheryl qrnq. Qhfg
327 Qvr jvgubhg zr, arire gunax zr. Jnyx evtug guebhtu zr, arire srry zr. Nyjnlf jngpuvat, arire fcrnxvat. Nyjnlf yhexvat, arire frra. Nve
328 Juvgr oveq, srngureyrff, sylvat bhg bs cnenqvfr. Sylvat bire frn naq ynaq. Qlvat va zl unaq. Fabj
329 Zl yvsr pna or zrnfherq va ubhef. V freir ol orvat qribherq. Guva, V nz dhvpx. Sng, V nz fybj. Jvaq vf zl sbr. Pnaqyr
330 Jung tbrf hc ohg arire pbzrf qbja? Ntr
331 Jr ner nyy nebhaq, lrg gb hf lbh ner unys oyvaq. Fhayvtug znxrf hf vaivfvoyr, naq qvssvphyg gb svaq. Fgnef
332 Jung'f ynetr ba Fngheqnl naq Fhaqnl. Fznyy ba Ghrfqnl, Jrqarfqnl, naq Guhefqnl, naq qvfnccrnef ba Zbaqnl naq Sevqnl? F
333 Jung qb lbh svyy jvgu rzcgl unaqf? Tybirf
334 Tbrf bire nyy gur uvyyf naq ubyybjf. Ovgrf uneq, ohg arire fjnyybjf. Sebfg
335 Fgrnygul nf n funqbj va gur qrnq bs avtug, phaavat ohg nssrpgvbangr vs tvira n ovgr. Arire bjarq ohg bsgra ybirq. Ng zl fcbeg pbafvqrerq pehry, ohg gung'f orpnhfr lbh arire xabj zr ng nyy. Png
336 N erq qehz juvpu fbhaqf jvgubhg orvat gbhpurq, naq tebjf fvyrag, jura vg vf gbhpurq. Urneg
337 Zl frpbaq vf cresbezrq ol zl svefg, naq vg vf gubhtug n guvrs ol gur znexf bs zl jubyr zvtug or pnhtug. Sbbgfgrc
338 Gur zna jub znqr vg qvqa'g arrq vg. Gur zna jub obhtug vg qvqa'g hfr vg. Gur zna jub hfrq vg qvqa'g jnag vg. Pbssva
339 N uvyy shyy, n ubyr shyy, lrg lbh pnaabg pngpu n objy shyy. Zvfg
340 V nz n obk gung ubyqf oynpx naq juvgr xrlf jvgubhg ybpxf. Lrg gurl pna haybpx lbhe fbhy. Cvnab
341 Jung vf bsgra erghearq, ohg arire obeebjrq/ Gunaxf
342 N zhggrerq ehzoyr jnf urneq sebz gur cra, naq V, va zl jnyxvat fgbccrq gb ybbx va. Jung jnf guvf V fnj? N znffvir ornfg, ubbsrq, naq wnjrq. Jvgu fcvxrf hcba vgf zvtugl oebj, V jngpurq nf ur fgehpx gur ghes naq cebjyrq. Naq lrg sbe nyy bs uvf zntavsvprapr, ur pbhyqa'g trg bhg bs gung jbbqra srapr. Ohyy
343 Jung jbeq unf xfg va gur zvqqyr, va gur ortvaavat, naq ng gur raq? Vaxfgnaq
344 Fb pbyq, qnzc naq qnex guvf cynpr. Gb fgnl lbh jbhyq ersenva, lrg gubfr jub bpphcl guvf cynpr qb arire pbzcynva. Tenir
345 Jung xvaq bs ahg vf rzcgl ng gur pragre naq unf ab furyy. Qbhtuahg
346 V unir n gvgyr naq znal cntrf. V nz n tragrry bs tragrry qrfprag. V nz n xvyyre irgrena bs jne. V nz n fynir gb zl ybeq cyrqtrq gb uvf freivpr. Xavtug
347 Bs gurfr guvatf - V unir gjb. Bar sbe zr - naq bar sbe lbh. Naq jura lbh nfx nobhg gur cevpr, V fvzcyl fzvyr naq abq gjvpr. Funevat
348 Ng avtug V pbzr jvgubhg orvat srgpurq. Ol qnl V nz ybfg jvgubhg orvat fgbyra. Fgnef
349 Evccrq sebz zl zbgure'f jbzo. Orngra naq ohearq, V orpbzr n oybbq guvefgl xvyyre. Veba
350 V'z irel grzcgvat, fb vgf fnvq, V unir n fuval pbng bs erq, naq zl syrfu vf juvgr orarngu. V fzryy fb fjrrg, gnfgr tbbq gb rng, naq uryc gb thneq lbhe grrgu. Nccyr
351 Gurl znqr zr n zbhgu, ohg qvqa'g tvir zr oerngu. Jngre tvirf zr yvsr, ohg gur fha oevatf zr qrngu. Fabjzna
352 V nz nf fvzcyr nf n pvepyr. Jbeguyrff nf n yrnqre, ohg jura V sbyybj n tebhc. Gurve fgeratgu vapernfrf grasbyq. Ol zlfrys V nz cenpgvpnyyl abguvat. Arvgure artngvir be cbfvgvir. 0
353 V fnj n zna va juvgr, ur ybbxrq dhvgr n fvtug. Ur jnf abg byq, ohg ur fgbbq va gur pbyq. Naq jura ur sryg gur fha, ur fgnegrq gb eha. Jub pbhyq ur or? Cyrnfr nafjre zr. Fabjzna
354 Jr ner svir yvggyr bowrpgf bs na rirelqnl fbeg. Lbh jvyy svaq hf nyy va n graavf pbheg. Ibjryf
355 Jung nyjnlf ehaf ohg arire jnyxf, bsgra zhezhef, arire gnyxf. Unf n orq ohg arire fyrrcf, unf n zbhgu ohg arire rngf? Evire
356 V pna or penpxrq, V pna or znqr. V pna or gbyq, V pna or cynlrq. Wbxr
357 Zl puvyqera ner arne naq sne. Ab znggre gung V xabj jurer gurl ner. Gur tvsg V tvir gurz znxr gurve qnl. Ohg vs V jrer tbar gurl jbhyq jnaqre njnl. Fha
358 Fpernzvat, fbnevat frrxvat fxl. Sybjref bs sver sylvat uvtu. Rnfgrea neg sebz napvrag gvzr. Anzr zr abj naq fbyir guvf eulzr. Sverjbex
359 Jub vf vg gung ebjf dhvpxyl jvgu sbhe bnef, ohg arire pbzrf bhg sebz haqre uvf bja ebbs? Ghegyr
360 Jub jbexf jura ur cynlf naq cynlf jura ur jbexf? Zhfvpvna
361 Zl svefg vf gjvpr va nccyr ohg abg bapr va gneg. Zl frpbaq vf va yvire ohg abg va urneg. Zl guveq vf va tvnag naq nyfb va tubfg. Jubyr V'z orfg jura V nz gbnfg. Cvt
362 Ernpuvat fgvssyl sbe gur fxl, V oner zl svatref jura vgf pbyq. Va jnezgu V jrne na rzrenyq tybir naq va orgjrra V qerff va tbyq. Gerr
363 N cerpvbhf fgbar, nf pyrne nf qvnzbaq. Frrx vg bhg juvyr gur fha'f arne gur ubevmba. Gubhtu lbh pna jnyx ba jngre jvgu vgf cbjre, gel gb xrrc vg, naq vg'yy inavfu va na ubhe. Vpr
364 Unys-jnl hc gur uvyy, V frr lbh ng ynfg, ylvat orarngu zr jvgu lbhe fbhaqf naq fvtugf. N pvgl va gur gjvyvtug, qvz naq infg, jvgu fzbxvat ebbsf, fbsg oryyf, naq tyrnzvat yvtugf. Cnfg
365 V urneq bs n jbaqre, bs jbeqf zbgu-rngra. Gung vf n fgenatr guvat, V gubhtug, jrveq. Gung n zna'f fbat or fjnyybjrq ol n jbez. Uvf oyvaqrq fragraprf, uvf orqfvqr fgnaq-ol ehfgyrq va gur avtug - naq gur eboore-thrfg. Abg bar jvg gur jvfre. Sbe gur jbeqf ur unq zhzoyrq. Obbxjbez
366 Jung unf n fvatyr rlr ohg pnaabg frr? Arrqyr
367 V'z yvtug nf n srngure, lrg gur fgebatrfg zna pna'g ubyq zr sbe zber guna 5 zvahgrf. Jung nz V? Oerngu
368 Jung tbrf va gur jngre oynpx naq pbzrf bhg erq? Ybofgre
369 Jung vf oebja naq fgvpxl? Fgvpx
370 Jung nfxf ohg arire nafjref? Bjy
371 Jung ybfrf vgf urnq va gur zbeavat naq trgf vg onpx ng avtug? Cvyybj
372 Jung ohvyqvat unf gur zbfg fgbevrf? Yvoenel
373 V bpphe bapr va n zvahgr... Z
374 V cnff orsber gur fha, ohg znxr ab funqbj. Jung nz V? jvaq
375 Yvtugre guna n srngure, ohg n zna pnaabg ubyq zr sbe ybat... oerngu
376 V unir n uhaqerq yrtf naq pnaabg fgnaq, n ybat arpx ohg ab urnq, naq V rng gur znvq'f yvsr. oebbz

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,51 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30804.86
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Sample_TextGame", "Sample_TextGame\Sample_TextGame.vcxproj", "{9095CB85-E1B0-4D03-9A3C-B3D277A1E300}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Sample_Template", "Sample_Template\Sample_Template.vcxproj", "{E48F8265-C836-4564-9525-AFB12295CF64}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Sample_Tests", "Sample_Tests\Sample_Tests.vcxproj", "{ABA88D0D-D79F-4371-BA63-D441662242B4}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{9095CB85-E1B0-4D03-9A3C-B3D277A1E300}.Debug|x64.ActiveCfg = Debug|x64
{9095CB85-E1B0-4D03-9A3C-B3D277A1E300}.Debug|x64.Build.0 = Debug|x64
{9095CB85-E1B0-4D03-9A3C-B3D277A1E300}.Debug|x86.ActiveCfg = Debug|Win32
{9095CB85-E1B0-4D03-9A3C-B3D277A1E300}.Debug|x86.Build.0 = Debug|Win32
{9095CB85-E1B0-4D03-9A3C-B3D277A1E300}.Release|x64.ActiveCfg = Release|x64
{9095CB85-E1B0-4D03-9A3C-B3D277A1E300}.Release|x64.Build.0 = Release|x64
{9095CB85-E1B0-4D03-9A3C-B3D277A1E300}.Release|x86.ActiveCfg = Release|Win32
{9095CB85-E1B0-4D03-9A3C-B3D277A1E300}.Release|x86.Build.0 = Release|Win32
{E48F8265-C836-4564-9525-AFB12295CF64}.Debug|x64.ActiveCfg = Debug|x64
{E48F8265-C836-4564-9525-AFB12295CF64}.Debug|x64.Build.0 = Debug|x64
{E48F8265-C836-4564-9525-AFB12295CF64}.Debug|x86.ActiveCfg = Debug|Win32
{E48F8265-C836-4564-9525-AFB12295CF64}.Debug|x86.Build.0 = Debug|Win32
{E48F8265-C836-4564-9525-AFB12295CF64}.Release|x64.ActiveCfg = Release|x64
{E48F8265-C836-4564-9525-AFB12295CF64}.Release|x64.Build.0 = Release|x64
{E48F8265-C836-4564-9525-AFB12295CF64}.Release|x86.ActiveCfg = Release|Win32
{E48F8265-C836-4564-9525-AFB12295CF64}.Release|x86.Build.0 = Release|Win32
{ABA88D0D-D79F-4371-BA63-D441662242B4}.Debug|x64.ActiveCfg = Debug|x64
{ABA88D0D-D79F-4371-BA63-D441662242B4}.Debug|x64.Build.0 = Debug|x64
{ABA88D0D-D79F-4371-BA63-D441662242B4}.Debug|x86.ActiveCfg = Debug|Win32
{ABA88D0D-D79F-4371-BA63-D441662242B4}.Debug|x86.Build.0 = Debug|Win32
{ABA88D0D-D79F-4371-BA63-D441662242B4}.Release|x64.ActiveCfg = Release|x64
{ABA88D0D-D79F-4371-BA63-D441662242B4}.Release|x64.Build.0 = Release|x64
{ABA88D0D-D79F-4371-BA63-D441662242B4}.Release|x86.ActiveCfg = Release|Win32
{ABA88D0D-D79F-4371-BA63-D441662242B4}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {B4AFD98E-6CC4-4427-A0B0-7E2A037C4A1F}
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,5 @@
#pragma once
#include "Logging/LogMacros.h"
//////////////////////////////////////////////////////////////////////////
DECLARE_LOG_CATEGORY_EXTERN(LogSquidTasks, Log, All);

View File

@ -0,0 +1,20 @@
#include "Modules/ModuleInterface.h"
#include "Modules/ModuleManager.h"
#include "SquidTasksLog.h"
DEFINE_LOG_CATEGORY(LogSquidTasks);
//////////////////////////////////////////////////////////////////////////
class FSquidTasksModule : public IModuleInterface
{
public:
void StartupModule() override
{
}
void ShutdownModule() override
{
}
};
//////////////////////////////////////////////////////////////////////////
IMPLEMENT_MODULE(FSquidTasksModule, SquidTasks);

View File

@ -0,0 +1,98 @@
#include "TaskDemoActor.h"
#include "SquidTasksLog.h"
#include "SquidTasks/FunctionGuard.h"
#include "Components/BoxComponent.h"
#include "Components/TextRenderComponent.h"
#include "DrawDebugHelpers.h"
// Utility tasks (local to this compilation unit)
namespace
{
Task<> CountSeconds(UBoxComponent* BoxComp, UTextRenderComponent* TextRenderComp)
{
// Restore text state when this coroutine collapses
auto RestoreTextGuard = MakeFnGuard([TextRenderComp, Text = TextRenderComp->Text, Color = TextRenderComp->TextRenderColor] {
TextRenderComp->SetText(Text);
TextRenderComp->SetTextRenderColor(Color);
});
// Count the seconds
float SecondsElapsed = 0.0f;
TextRenderComp->SetTextRenderColor(FColor::Green);
while(true)
{
TextRenderComp->SetText(FText::FromString(FString::SanitizeFloat(SecondsElapsed)));
co_await WaitSeconds(1.0f, GameTime(BoxComp));
++SecondsElapsed;
}
}
Task<> DebugDrawBoxComponent(UBoxComponent* BoxComp)
{
while(true)
{
// Calculate correct color (green when overlapping, otherwise red)
bool bIsOverlapping = BoxComp->GetOverlapInfos().Num() > 0;
FColor Color = bIsOverlapping ? FColor::Green : FColor::Red;
// Draw the box
DrawDebugBox(BoxComp->GetWorld(), BoxComp->GetCenterOfMass(), BoxComp->GetScaledBoxExtent(), Color);
// Wait until next frame
co_await Suspend();
}
}
}
//--- ATaskDemoActor ---//
ATaskDemoActor::ATaskDemoActor()
{
// Create box component (as root)
BoxComp = CreateDefaultSubobject<UBoxComponent>(TEXT("BoxComp"));
BoxComp->SetBoxExtent(FVector{ 200.0f, 200.0f, 200.0f }, false);
RootComponent = BoxComp;
// Create text render component
TextRenderComp = CreateDefaultSubobject<UTextRenderComponent>(TEXT("TextRenderComp"));
TextRenderComp->SetupAttachment(BoxComp);
TextRenderComp->HorizontalAlignment = EHTA_Center;
TextRenderComp->VerticalAlignment = EVRTA_TextCenter;
TextRenderComp->Text = FText::FromString(TEXT("Enter the box"));
TextRenderComp->SetWorldSize(52.0f);
// Make this actor tick
PrimaryActorTick.bCanEverTick = true;
}
void ATaskDemoActor::BeginPlay()
{
Super::BeginPlay();
TaskMgr.RunManaged(ManageActor());
TaskMgr.RunManaged(DebugDrawBoxComponent(BoxComp));
}
void ATaskDemoActor::Tick(float DT)
{
Super::Tick(DT);
TaskMgr.Update();
}
void ATaskDemoActor::EndPlay(const EEndPlayReason::Type EPR)
{
TaskMgr.KillAllTasks();
Super::EndPlay(EPR);
}
Task<> ATaskDemoActor::ManageActor()
{
TASK_NAME(__FUNCTION__);
while(true)
{
// Wait until anything overlaps this volume
co_await WaitUntil([BoxComp = BoxComp] {
return BoxComp->GetOverlapInfos().Num() > 0;
});
// Run a sub-task that counts off seconds while something is overlapping the volume
co_await CountSeconds(BoxComp, TextRenderComp).CancelIf([BoxComp = BoxComp] {
return BoxComp->GetOverlapInfos().Num() == 0;
});
}
}

View File

@ -0,0 +1,30 @@
#pragma once
#include "SquidTasks/Task.h"
#include "SquidTasks/TaskManager.h"
#include "TaskDemoActor.generated.h"
class UBoxComponent;
class UTextRenderComponent;
// Task Demo Actor
UCLASS()
class ATaskDemoActor : public AActor
{
GENERATED_BODY()
public:
ATaskDemoActor();
virtual void BeginPlay() override;
virtual void Tick(float DT) override;
virtual void EndPlay(const EEndPlayReason::Type EPR) override;
protected:
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Task Demo") UBoxComponent* BoxComp = nullptr;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Task Demo") UTextRenderComponent* TextRenderComp = nullptr;
private:
TaskManager TaskMgr;
Task<> ManageActor();
};

View File

@ -0,0 +1,128 @@
#pragma once
/// @defgroup FunctionGuard Function Guard
/// @brief Scope guard that calls a function as it leaves scope.
/// @{
///
/// A FunctionGuard is an scope guard object that stores a functor that will be called from its destructor. By
/// convention, scope guards are move-only objects that are intended for allocation on the stack, to ensure that certain
/// operations are performed exactly once (when their scope collapses).
///
/// Because tasks can be canceled while suspended (and thus do not reach the end of the function), any cleanup code at
/// the end of a task isn't guaranteed to execute. Because FunctionGuard is an RAII object, it gives programmers an
/// opportunity to schedule guaranteed cleanup code, no matter how a task terminates.
///
/// Consider the following example of a task that manages a character's "charge attack" in a combat-oriented game:
///
/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
///
/// class Character : public Actor
/// {
/// public:
/// Task<> ChargeAttackState()
/// {
/// bool bIsFullyCharged = false;
/// if(Input->IsAttackButtonPressed())
/// {
/// StartCharging(); // Start playing charge effects
/// auto stopChargingGuard = MakeFnGuard([&]{
/// StopCharging(); // Stop playing charge effects
/// });
///
/// // Wait for N seconds (canceling if button is no longer held)
/// bIsFullyCharged = co_await WaitSeconds(chargeTime).CancelIf([&] {
/// return !Input->IsAttackButtonPressed();
/// });
/// } // <-- This is when StopCharging() will be called
/// FireShot(bIsFullyCharged);
/// }
/// };
///
/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
///
/// In the above example, we can guarantee that StopCharging will logically be called exactly once for every call to
/// StartCharging(), even the ChargeAttackState() task is killed or canceled. Furthermore, we know that StopCharging()
/// will always be called prior to the call to FireShot().
///
/// In practice, it is often desirable to create more domain-specific scope guards for specific use cases, but
/// FunctionGuard provides a simple general-purpose tool for writing robust, water-tight coroutine logic without the
/// overhead of creating bespoke support classes.
//--- User configuration header ---//
#include "TasksConfig.h"
NAMESPACE_SQUID_BEGIN
template <typename tFn = TFunction<void()>>
class FunctionGuard
{
public:
FunctionGuard() = default; /// Default constructor
FunctionGuard(nullptr_t) /// Null-pointer constructor
{
}
FunctionGuard(tFn in_fn) /// Functor constructor
: m_fn(MoveTemp(in_fn))
{
}
~FunctionGuard() /// Destructor
{
Execute();
}
FunctionGuard(FunctionGuard&& in_other) noexcept /// Move constructor
: m_fn(MoveTemp(in_other.m_fn))
{
in_other.Forget();
}
FunctionGuard& operator=(FunctionGuard<tFn>&& in_other) noexcept /// Move assignment operator
{
m_fn = MoveTemp(in_other.m_fn);
in_other.Forget();
return *this;
}
FunctionGuard& operator=(nullptr_t) noexcept /// Null-pointer assignment operator (calls Forget() to clear the functor)
{
Forget();
return *this;
}
operator bool() const /// Convenience conversion operator that calls IsBound()
{
return IsBound();
}
bool IsBound() noexcept /// Returns whether functor has been bound to this FunctionGuard
{
return m_fn;
}
void Execute() /// Executes and clears the functor (if bound)
{
if(m_fn)
{
m_fn.GetValue()();
Forget();
}
}
void Forget() noexcept /// Clear the functor (without calling it)
{
m_fn.Reset();
}
private:
TOptional<tFn> m_fn; // The function to call when this scope guard is destroyed
};
/// Create a function guard (directly stores the concretely-typed functor in the FunctionGuard)
template <typename tFn>
FunctionGuard<tFn> MakeFnGuard(tFn in_fn)
{
return FunctionGuard<tFn>(MoveTemp(in_fn));
}
/// Create a generic function guard (preferable when re-assigning new functor values to the same variable)
inline FunctionGuard<> MakeGenericFnGuard(TFunction<void()> in_fn)
{
return FunctionGuard<>(MoveTemp(in_fn));
}
NAMESPACE_SQUID_END
///@} end of FunctionGuard group

View File

@ -0,0 +1,220 @@
// WARNING: This is an internal implementation header, which must be included from a specific location/namespace
// That is the reason that this header does not contain a #pragma once, nor namespace guards
// Helper struct representing a transition event to a new FSM state
struct TransitionEvent
{
Task<> newTask;
StateId newStateId;
};
// Base class for defining links between states
class LinkBase
{
public:
virtual ~LinkBase() = default;
virtual TOptional<TransitionEvent> EvaluateLink(const tOnStateTransitionFn& in_onTransitionFn) const = 0;
};
// Type-safe link handle
class LinkHandle
{
bool IsOnCompleteLink() const
{
return m_linkType == eType::OnComplete;
}
bool HasCondition() const
{
return m_isConditionalLink;
}
protected:
// Link-type enum
enum class eType
{
Normal,
OnComplete,
};
// Friends
template<class, class> friend class StateHandle;
friend class ::TaskFSM;
// Constructors (friend-only)
LinkHandle() = delete;
LinkHandle(TSharedPtr<LinkBase> in_link, eType in_linkType, bool in_isConditional)
: m_link(MoveTemp(in_link))
, m_linkType(in_linkType)
, m_isConditionalLink(in_isConditional)
{
}
TOptional<TransitionEvent> EvaluateLink(const tOnStateTransitionFn& in_onTransitionFn) const
{
return m_link->EvaluateLink(in_onTransitionFn);
}
private:
TSharedPtr<LinkBase> m_link; // The underlying link
eType m_linkType; // Whether the link is normal or OnComplete
bool m_isConditionalLink; // Whether the link has an associated condition predicate
};
// Internal FSM state object
template<class tStateInput, class tStateConstructorFn>
struct State
{
State(tStateConstructorFn in_stateCtorFn, StateId in_stateId, FString in_debugName)
: stateCtorFn(in_stateCtorFn)
, stateId(in_stateId)
, debugName(in_debugName)
{
}
tStateConstructorFn stateCtorFn;
StateId stateId;
FString debugName;
};
// Internal FSM state object (exit state specialization)
template<>
struct State<void, void>
{
State(StateId in_stateId, FString in_debugName)
: stateId(in_stateId)
, debugName(in_debugName)
{
}
StateId stateId;
FString debugName;
};
// Internal link definition object
template<class ReturnT, class tStateConstructorFn, class tPredicateFn>
class Link : public LinkBase
{
public:
Link(TSharedPtr<State<ReturnT, tStateConstructorFn>> in_targetState, tPredicateFn in_predicate)
: m_targetState(MoveTemp(in_targetState))
, m_predicate(in_predicate)
{
}
private:
virtual TOptional<TransitionEvent> EvaluateLink(const tOnStateTransitionFn& in_onTransitionFn) const final
{
TOptional<TransitionEvent> result;
if(TOptional<ReturnT> payload = m_predicate())
{
if(in_onTransitionFn)
{
in_onTransitionFn();
}
result = TransitionEvent{ m_targetState->stateCtorFn(payload.GetValue()), m_targetState->stateId };
}
return result;
}
TSharedPtr<State<ReturnT, tStateConstructorFn>> m_targetState;
tPredicateFn m_predicate;
};
// Internal link definition object (no-payload specialization)
template<class tStateConstructorFn, class tPredicateFn>
class Link<void, tStateConstructorFn, tPredicateFn> : public LinkBase
{
public:
Link(TSharedPtr<State<void, tStateConstructorFn>> in_targetState, tPredicateFn in_predicate)
: m_targetState(MoveTemp(in_targetState))
, m_predicate(in_predicate)
{
}
private:
virtual TOptional<TransitionEvent> EvaluateLink(const tOnStateTransitionFn& in_onTransitionFn) const final
{
TOptional<TransitionEvent> result;
if(m_predicate())
{
if(in_onTransitionFn)
{
in_onTransitionFn();
}
result = TransitionEvent{ m_targetState->stateCtorFn(), m_targetState->stateId };
}
return result;
}
TSharedPtr<State<void, tStateConstructorFn>> m_targetState;
tPredicateFn m_predicate;
};
// Internal link definition object (exit-state specialization)
template<class tPredicateFn>
class Link<void, void, tPredicateFn> : public LinkBase
{
public:
Link(TSharedPtr<State<void, void>> in_targetState, tPredicateFn in_predicate)
: m_targetState(MoveTemp(in_targetState))
, m_predicate(in_predicate)
{
}
private:
virtual TOptional<TransitionEvent> EvaluateLink(const tOnStateTransitionFn& in_onTransitionFn) const final
{
TOptional<TransitionEvent> result;
if(m_predicate())
{
if(in_onTransitionFn)
{
in_onTransitionFn();
}
result = TransitionEvent{ Task<>(), m_targetState->stateId };
}
return result;
}
TSharedPtr<State<void, void>> m_targetState;
tPredicateFn m_predicate;
};
// Specialized type traits that deduce the first argument type of an arbitrary callable type
template <typename tRet, typename tArg>
static tArg get_first_arg_type(TFunction<tRet(tArg)> f); // Return type is first argument type
template <typename tRet>
static void get_first_arg_type(TFunction<tRet()> f); // Return type is void (function has no arguments)
template <typename T>
struct function_traits : public function_traits<decltype(&T::operator())> // Generic callable objects (use operator())
{
};
template <typename tRet, typename... tArgs> // Function
struct function_traits<tRet(tArgs...)>
{
using tFunction = TFunction<tRet(tArgs...)>;
using tArg = decltype(get_first_arg_type(tFunction()));
};
template <typename tRet, typename... tArgs> // Function ptr
struct function_traits<tRet(*)(tArgs...)>
{
using tFunction = TFunction<tRet(tArgs...)>;
using tArg = decltype(get_first_arg_type(tFunction()));
};
template <typename tClass, typename tRet, typename... tArgs> // Member function ptr (const)
struct function_traits<tRet(tClass::*)(tArgs...) const>
{
using tFunction = TFunction<tRet(tArgs...)>;
using tArg = decltype(get_first_arg_type(tFunction()));
};
template <typename tClass, typename tRet, typename... tArgs> // Member function ptr
struct function_traits<tRet(tClass::*)(tArgs...)>
{
using tFunction = TFunction<tRet(tArgs...)>;
using tArg = decltype(get_first_arg_type(tFunction()));
};

View File

@ -0,0 +1,896 @@
// WARNING: This is an internal implementation header, which must be included from a specific location/namespace
// That is the reason that this header does not contain a #pragma once, nor namespace guards
enum class eTaskRef;
template <typename tRet> class TaskPromise;
class TaskInternalBase;
template <typename tRet> class TaskInternal;
//--- tTaskReadyFn ---//
using tTaskReadyFn = TFunction<bool()>;
template <typename tRet, eTaskRef RefType, eTaskResumable Resumable>
auto CancelTaskIf(Task<tRet, RefType, Resumable>&& in_task, tTaskCancelFn in_cancelFn);
template <typename tRet, eTaskRef RefType, eTaskResumable Resumable>
auto StopTaskIf(Task<tRet, RefType, Resumable>&& in_task, tTaskCancelFn in_cancelFn);
template <typename tRet, eTaskRef RefType, eTaskResumable Resumable, typename tTimeFn>
auto StopTaskIf(Task<tRet, RefType, Resumable>&& in_task, tTaskCancelFn in_cancelFn, tTaskTime in_timeout, tTimeFn in_timeFn);
template <typename tRet, eTaskRef RefType, eTaskResumable Resumable, typename T>
auto StopTaskIf(Task<tRet, RefType, Resumable>&& in_task, tTaskCancelFn in_cancelFn, tTaskTime in_timeout);
//--- Suspend-If Awaiter ---//
struct SuspendIf
{
SuspendIf(bool in_suspend)
: m_suspend(in_suspend)
{
}
bool await_ready() noexcept { return !m_suspend; }
void await_suspend(std::coroutine_handle<>) noexcept {}
void await_resume() noexcept {}
private:
bool m_suspend;
};
//--- Task Debug Stack Formatter ---//
struct TaskDebugStackFormatter
{
// Format function (formats a debug output string) [virtual]
virtual FString Format(const FString& in_str) const
{
FString result = Indent(0);
int32_t indent = 0;
int32_t start = 0;
int32_t found = 0;
while((found = in_str.FindChar('\n', start)) != INDEX_NONE)
{
int32_t end = found + 1;
if((found < in_str.Len() - 1) && (in_str[found + 1] == '`')) // indent
{
++indent;
++end;
}
else if((found >= 1) && (in_str[found - 1] == '`')) // dedent
{
--indent;
--found;
}
result += in_str.Mid(start, found - start) + '\n' + Indent(indent);
start = end;
}
result += in_str.Mid(start);
return result;
}
virtual FString Indent(int32_t in_indent) const
{
return FString::ChrN(in_indent * 2, ' ');
}
};
static FString FormatDebugString(FString in_str)
{
in_str.ReplaceCharInline('\n', ' ');
in_str.LeftChopInline(32, false);
return in_str;
}
//--- SetDebugName Awaiter ---//
#if SQUID_ENABLE_TASK_DEBUG
struct SetDebugName
{
// Sets a Task's debug name field
SetDebugName(const char* in_name)
: m_name(in_name)
{
}
SetDebugName(const char* in_name, TFunction<FString()> in_dataFn)
: m_name(in_name)
, m_dataFn(in_dataFn)
{
}
private:
template <typename tRet> friend class TaskPromiseBase;
const char* m_name = nullptr;
TFunction<FString()> m_dataFn;
};
#endif //SQUID_ENABLE_TASK_DEBUG
//--- AddStopTask Awaiter ---//
template <typename tRet, eTaskRef RefType, eTaskResumable Resumable>
struct AddStopTaskAwaiter
{
AddStopTaskAwaiter(Task<tRet, RefType, Resumable>& in_taskToStop)
: m_taskToStop(&in_taskToStop)
{
}
private:
template <typename tRet> friend class TaskPromiseBase;
Task<tRet, RefType, Resumable>* m_taskToStop = nullptr;
};
template <typename tRet, eTaskRef RefType, eTaskResumable Resumable>
auto AddStopTask(Task<tRet, RefType, Resumable>& in_taskToStop)
{
return AddStopTaskAwaiter<tRet, RefType, Resumable>(in_taskToStop);
};
//--- RemoveStopTask Awaiter ---//
template <typename tRet, eTaskRef RefType, eTaskResumable Resumable>
struct RemoveStopTaskAwaiter
{
RemoveStopTaskAwaiter(Task<tRet, RefType, Resumable>& in_taskToStop)
: m_taskToStop(&in_taskToStop)
{
}
private:
template <typename tRet> friend class TaskPromiseBase;
Task<tRet, RefType, Resumable>* m_taskToStop = nullptr;
};
template <typename tRet, eTaskRef RefType, eTaskResumable Resumable>
auto RemoveStopTask(Task<tRet, RefType, Resumable>& in_taskToStop)
{
return RemoveStopTaskAwaiter<tRet, RefType, Resumable>(in_taskToStop);
};
//--- Task Awaiter ---//
template <typename tRet, eTaskRef RefType, eTaskResumable Resumable, typename promise_type>
struct TaskAwaiterBase
{
TaskAwaiterBase(const Task<tRet, RefType, Resumable>& in_task)
{
// This constructor exists to minimize downstream compile-error spam when co_awaiting a non-copyable Task by copy
}
TaskAwaiterBase(Task<tRet, RefType, Resumable>&& in_task)
: m_task(MoveTemp(in_task))
{
SQUID_RUNTIME_CHECK(m_task.IsValid(), "Tried to await an invalid task");
}
TaskAwaiterBase(TaskAwaiterBase&& in_taskAwaiter) noexcept
{
m_task = MoveTemp(in_taskAwaiter.m_task);
}
bool await_ready() noexcept
{
if(m_task.IsDone())
{
return true;
}
return false;
}
template <eTaskResumable UResumable = Resumable, typename std::enable_if_t<UResumable == eTaskResumable::Yes>* = nullptr>
bool await_suspend(std::coroutine_handle<promise_type> in_coroHandle) noexcept
{
// Set the sub-task on the suspending task
auto& promise = in_coroHandle.promise();
auto taskInternal = promise.GetInternalTask();
auto subTaskInternal = m_task.GetInternalTask();
if(taskInternal->IsStopRequested())
{
subTaskInternal->RequestStop(); // Propagate any stop request to new sub-tasks
}
taskInternal->SetSubTask(StaticCastSharedPtr<TaskInternalBase>(subTaskInternal));
// Resume the task
if(m_task.Resume() == eTaskStatus::Done)
{
taskInternal->SetSubTask(nullptr);
return false; // Do not suspend, because the task is done
}
return true; // Suspend, because the task is not done
}
template <eTaskResumable UResumable = Resumable, typename std::enable_if_t<UResumable == eTaskResumable::No>* = nullptr>
bool await_suspend(std::coroutine_handle<promise_type> in_coroHandle) noexcept
{
auto& promise = in_coroHandle.promise();
if(!m_task.IsDone())
{
promise.SetReadyFunction([this] { return m_task.IsDone(); });
return true; // Suspend, because the task is not done
}
return false; // Do not suspend, because the task is done
}
protected:
auto GetInternalTask() const
{
return m_task.GetInternalTask();
}
Task<tRet, RefType, Resumable> m_task;
};
template <typename tRet, eTaskRef RefType, eTaskResumable Resumable, typename promise_type>
struct TaskAwaiter : public TaskAwaiterBase<tRet, RefType, Resumable, promise_type>
{
using TaskAwaiterBase<tRet, RefType, Resumable, promise_type>::TaskAwaiterBase;
template <typename U = tRet, typename std::enable_if_t<!std::is_void<U>::value>* = nullptr>
auto await_resume()
{
this->m_task.RethrowUnhandledException(); // Re-throw any exceptions
auto retVal = this->m_task.TakeReturnValue();
SQUID_RUNTIME_CHECK(retVal, "Awaited task return value is unset");
return MoveTemp(retVal.GetValue());
}
template <typename U = tRet, typename std::enable_if_t<std::is_void<U>::value>* = nullptr>
void await_resume()
{
this->m_task.RethrowUnhandledException(); // Re-throw any exceptions
}
};
//--- Future Awaiter ---//
template <typename tRet, typename promise_type>
struct FutureAwaiter
{
FutureAwaiter(TFuture<tRet>&& in_future)
: m_future(MoveTemp(in_future))
{
}
~FutureAwaiter()
{
}
FutureAwaiter(FutureAwaiter&& in_futureAwaiter) noexcept
{
m_future = MoveTemp(in_futureAwaiter.m_future);
}
bool await_ready() noexcept
{
bool isReady = m_future.IsReady();
return isReady;
}
bool await_suspend(std::coroutine_handle<promise_type> in_coroHandle) noexcept
{
// Set the ready function
auto& promise = in_coroHandle.promise();
// Suspend if future is not ready
bool shouldSuspend = !m_future.IsReady();
if(shouldSuspend)
{
promise.SetReadyFunction([this] { return m_future.IsReady(); });
}
return shouldSuspend;
}
template <typename U = tRet, typename std::enable_if_t<!std::is_void<U>::value>* = nullptr>
auto await_resume()
{
return m_future.Get();
}
template <typename U = tRet, typename std::enable_if_t<std::is_void<U>::value>* = nullptr>
void await_resume()
{
m_future.Get();
}
private:
TFuture<tRet> m_future;
};
//--- Shared Future Awaiter ---//
template <typename tRet, typename promise_type>
struct SharedFutureAwaiter
{
SharedFutureAwaiter(const TSharedFuture<tRet>& in_sharedFuture)
: m_sharedFuture(in_sharedFuture)
{
}
bool await_ready() noexcept
{
bool isReady = m_sharedFuture.IsReady();
return isReady;
}
bool await_suspend(std::coroutine_handle<promise_type> in_coroHandle) noexcept
{
// Set the ready function
auto& promise = in_coroHandle.promise();
// Suspend if future is not ready
bool shouldSuspend = !m_sharedFuture.IsReady();
if(shouldSuspend)
{
promise.SetReadyFunction([this] { return m_sharedFuture.IsReady(); });
}
return shouldSuspend;
}
template <typename U = tRet, typename std::enable_if_t<!std::is_void<U>::value>* = nullptr>
auto await_resume()
{
return m_sharedFuture.Get();
}
template <typename U = tRet, typename std::enable_if_t<std::is_void<U>::value>* = nullptr>
void await_resume()
{
m_sharedFuture.Get(); // Trigger any pending errors
}
private:
TSharedFuture<tRet> m_sharedFuture;
};
//--- TaskPromiseBase ---//
template <typename tRet>
class alignas(16) TaskPromiseBase
{
public:
// Type aliases
using promise_type = TaskPromise<tRet>;
using tTaskInternal = TaskInternal<tRet>;
// Destructor
~TaskPromiseBase()
{
// NOTE: Destructor is non-virtual, because it is always handled + destroyed as its concrete type
m_taskInternal->OnTaskPromiseDestroyed();
}
// Coroutine interface functions
auto initial_suspend() noexcept
{
return std::suspend_always();
}
auto final_suspend() noexcept
{
return std::suspend_always();
}
auto get_return_object()
{
return std::coroutine_handle<promise_type>::from_promise(*static_cast<promise_type*>(this));
}
static TSharedPtr<tTaskInternal> get_return_object_on_allocation_failure()
{
SQUID_THROW(std::bad_alloc(), "Failed to allocate memory for Task");
return {};
}
//----------------------------------------------------------------------------
// HACK: Coroutines in UE5 under MSVC is currently causing a memory underrun
// These allocators are a workaround for the issue (as is alignas(16))
void* operator new(size_t Size) noexcept
{
const size_t WorkaroundAlign = std::alignment_of<TaskPromiseBase>();
Size += WorkaroundAlign;
return (void*)((uint8_t*)FMemory::Malloc(Size, WorkaroundAlign) + WorkaroundAlign);
}
void operator delete(void* Ptr) noexcept
{
const size_t WorkaroundAlign = std::alignment_of<TaskPromiseBase>();
auto OffsetPtr = (uint8_t*)Ptr - WorkaroundAlign;
FMemory::Free(OffsetPtr);
}
//----------------------------------------------------------------------------
#if SQUID_NEEDS_UNHANDLED_EXCEPTION
void unhandled_exception() noexcept
{
#if SQUID_USE_EXCEPTIONS
// Propagate exceptions for handling
m_taskInternal->SetUnhandledException(std::current_exception());
#endif //SQUID_USE_EXCEPTIONS
}
#endif // SQUID_NEEDS_UNHANDLED_EXCEPTION
// Internal Task
void SetInternalTask(tTaskInternal* in_taskInternal)
{
m_taskInternal = in_taskInternal;
}
tTaskInternal* GetInternalTask()
{
return m_taskInternal;
}
const tTaskInternal* GetInternalTask() const
{
return m_taskInternal;
}
// Ready Function
void SetReadyFunction(const tTaskReadyFn& in_taskReadyFn)
{
m_taskInternal->SetReadyFunction(in_taskReadyFn);
}
// Await-Transforms
auto await_transform(Suspend in_awaiter)
{
return in_awaiter;
}
auto await_transform(std::suspend_never in_awaiter)
{
return in_awaiter;
}
#if SQUID_ENABLE_TASK_DEBUG
auto await_transform(SetDebugName in_awaiter)
{
m_taskInternal->SetDebugName(in_awaiter.m_name);
m_taskInternal->SetDebugDataFn(in_awaiter.m_dataFn);
return std::suspend_never();
}
#endif //SQUID_ENABLE_TASK_DEBUG
template <typename tRet, eTaskRef RefType, eTaskResumable Resumable>
auto await_transform(AddStopTaskAwaiter<tRet, RefType, Resumable> in_awaiter)
{
m_taskInternal->AddStopTask(*in_awaiter.m_taskToStop);
return std::suspend_never();
}
template <typename tRet, eTaskRef RefType, eTaskResumable Resumable>
auto await_transform(RemoveStopTaskAwaiter<tRet, RefType, Resumable> in_awaiter)
{
m_taskInternal->RemoveStopTask(*in_awaiter.m_taskToStop);
return std::suspend_never();
}
auto await_transform(GetStopContext in_awaiter)
{
struct GetStopContextAwaiter : public std::suspend_never
{
GetStopContextAwaiter(StopContext in_stopCtx)
: stopCtx(in_stopCtx)
{
}
auto await_resume() noexcept
{
return stopCtx;
}
StopContext stopCtx;
};
GetStopContextAwaiter stopCtxAwaiter{ m_taskInternal->GetStopContext() };
return stopCtxAwaiter;
}
auto await_transform(const tTaskReadyFn& in_taskReadyFn)
{
// Check if we are already ready, and suspend if we are not
bool isReady = in_taskReadyFn();
if(!isReady)
{
m_taskInternal->SetReadyFunction(in_taskReadyFn);
}
return SuspendIf(!isReady); // Suspend if the function isn't already ready
}
template <typename tFutureRet>
auto await_transform(TFuture<tFutureRet>&& in_future)
{
return FutureAwaiter<tFutureRet, promise_type>(MoveTemp(in_future));
}
template <typename tFutureRet>
auto await_transform(const TSharedFuture<tFutureRet>& in_sharedFuture)
{
return SharedFutureAwaiter<tFutureRet, promise_type>(in_sharedFuture);
}
// Task Await-Transforms
template <typename tTaskRet, eTaskRef RefType, eTaskResumable Resumable,
typename std::enable_if_t<Resumable == eTaskResumable::Yes>* = nullptr>
auto await_transform(Task<tTaskRet, RefType, Resumable>&& in_task) // Move version
{
return TaskAwaiter<tTaskRet, RefType, Resumable, promise_type>(MoveTemp(in_task));
}
template <typename tTaskRet, eTaskRef RefType, eTaskResumable Resumable,
typename std::enable_if_t<Resumable == eTaskResumable::No>* = nullptr>
auto await_transform(Task<tTaskRet, RefType, Resumable> in_task) // Copy version (Non-Resumable)
{
return TaskAwaiter<tTaskRet, RefType, Resumable, promise_type>(MoveTemp(in_task));
}
template <typename tTaskRet, eTaskRef RefType, eTaskResumable Resumable,
typename std::enable_if_t<Resumable == eTaskResumable::Yes>* = nullptr>
auto await_transform(const Task<tTaskRet, RefType, Resumable>& in_task) // Invalid copy version (Resumable)
{
static_assert(static_false<tTaskRet>::value, "Cannot await a non-copyable (resumable) Task by copy (try co_await MoveTemp(task), co_await WeakTaskHandle(task), or co_await task.WaitUntilDone()");
return TaskAwaiter<tTaskRet, RefType, Resumable, promise_type>(MoveTemp(in_task));
}
protected:
tTaskInternal* m_taskInternal = nullptr;
};
//--- TaskPromise ---//
template <typename tRet>
class TaskPromise : public TaskPromiseBase<tRet>
{
public:
// Return value access
void return_value(const tRet& in_retVal) // Copy return value
{
this->m_taskInternal->SetReturnValue(in_retVal);
}
void return_value(tRet&& in_retVal) // Move return value
{
this->m_taskInternal->SetReturnValue(MoveTemp(in_retVal));
}
};
template <>
class TaskPromise<void> : public TaskPromiseBase<void>
{
public:
void return_void()
{
}
};
//--- TaskInternalBase ---//
class TaskInternalBase
{
public:
TaskInternalBase(std::coroutine_handle<> in_coroHandle)
: m_coroHandle(in_coroHandle)
{
SQUID_RUNTIME_CHECK(m_coroHandle, "Invalid coroutine handle passed into Task");
}
~TaskInternalBase() // NOTE: Destructor is intentionally non-virtual (shared_ptr preserves concrete type via deleter)
{
Kill(); // Used for killing subtasks
}
StopContext GetStopContext() const
{
return { &m_isStopRequested };
}
bool IsStopRequested() const
{
return m_isStopRequested;
}
void RequestStop() // Propagates a request for the task to come to a 'graceful' stop
{
m_isStopRequested = true;
for(auto& stopTask : m_stopTasks)
{
if(auto locked = stopTask.Pin())
{
locked->RequestStop();
}
}
m_stopTasks.SetNum(0);
}
template <typename tRet, eTaskRef RefType, eTaskResumable Resumable>
void AddStopTask(Task<tRet, RefType, Resumable>& in_taskToStop) // Adds a task to the list of tasks to which we propagate stop requests
{
if(m_isStopRequested)
{
in_taskToStop.RequestStop();
}
else if(in_taskToStop.IsValid())
{
m_stopTasks.Add(in_taskToStop.GetInternalTask());
}
}
template <typename tRet, eTaskRef RefType, eTaskResumable Resumable>
void RemoveStopTask(Task<tRet, RefType, Resumable>& in_taskToStop) // Removes a task to the list of tasks to which we propagate stop requests
{
if(in_taskToStop.IsValid())
{
for(int32_t i = 0; i < m_stopTasks.Num(); ++i)
{
if(m_stopTasks[i].Pin() == in_taskToStop.GetInternalTask())
{
m_stopTasks[i] = m_stopTasks.Last();
m_stopTasks.Pop();
return;
}
}
}
}
eTaskStatus Resume() // Returns whether the task is still running
{
// Make sure this task is not already mid-resume
SQUID_RUNTIME_CHECK(m_internalState != eInternalState::Resuming, "Attempted to resume Task while already resumed");
// Task is destroyed, therefore task is done
if(m_internalState == eInternalState::Destroyed)
{
return eTaskStatus::Done;
}
// Mark task as resuming
m_internalState = eInternalState::Resuming;
// Resume any active sub-task
if(m_subTaskInternal)
{
// Propagate any stop requests to sub-task prior to resuming
if(m_isStopRequested)
{
m_subTaskInternal->m_isStopRequested = true;
}
// Resume the sub-task
if(m_subTaskInternal->Resume() != eTaskStatus::Done)
{
m_internalState = eInternalState::Idle;
return eTaskStatus::Suspended; // Sub-task not done, therefore task is not done
}
// Clear the sub-task
m_subTaskInternal = nullptr;
}
// Resume task, if necessary
if(CanResume())
{
m_taskReadyFn = nullptr; // Clear any ready function we were waiting on
m_coroHandle.resume(); // Resume the underlying std::coroutine_handle
}
// Return to idle state and return current task status
auto taskStatus = m_coroHandle.done() ? eTaskStatus::Done : eTaskStatus::Suspended;
if(taskStatus == eTaskStatus::Done)
{
m_isDone = true; // Mark task done
}
m_internalState = eInternalState::Idle;
return taskStatus;
}
// Sub-task
void SetSubTask(TSharedPtr<TaskInternalBase> in_subTaskInternal)
{
m_subTaskInternal = in_subTaskInternal;
}
#if SQUID_ENABLE_TASK_DEBUG
// Debug task name + stack
FString GetDebugName() const
{
return (!IsDone() && m_debugDataFn) ? (FString(m_debugName) + " [" + m_debugDataFn() + "]") : m_debugName;
}
FString GetDebugStack() const
{
FString result = m_subTaskInternal ? (GetDebugName() + " -> " + m_subTaskInternal->GetDebugStack()) : GetDebugName();
return result;
}
void SetDebugName(const char* in_debugName)
{
if(in_debugName)
{
m_debugName = in_debugName;
}
}
void SetDebugDataFn(TFunction<FString()> in_debugDataFn)
{
m_debugDataFn = in_debugDataFn;
}
#endif //SQUID_ENABLE_TASK_DEBUG
// Exceptions
#if SQUID_USE_EXCEPTIONS
std::exception_ptr GetUnhandledException() const
{
if(m_isExceptionSet)
{
return m_exception;
}
return nullptr;
}
#endif //SQUID_USE_EXCEPTIONS
protected:
#if SQUID_USE_EXCEPTIONS
// Internal implementation of exception-setting (called by TaskInternal<> child classes)
void InternalSetUnhandledException(std::exception_ptr in_exception)
{
// NOTE: This must never be called more than once in the lifetime of an internal task
SQUID_RUNTIME_CHECK(!m_isExceptionSet, "Exception was set for a task after it had already been set");
if(!m_isExceptionSet)
{
m_exception = in_exception;
m_isExceptionSet = true;
}
}
#endif //SQUID_USE_EXCEPTIONS
private:
template <typename tRet> friend class TaskPromiseBase;
template <typename tRet, eTaskRef RefType, eTaskResumable Resumable, typename promise_type> friend struct TaskAwaiterBase;
template <typename tRet, eTaskRef RefType, eTaskResumable Resumable> friend class Task;
// Kill this task
void Kill() // Kill() can safely be called multiple times
{
SQUID_RUNTIME_CHECK(m_internalState != eInternalState::Resuming, "Attempted to kill Task while resumed");
if(m_internalState == eInternalState::Idle)
{
// Mark task done
m_isDone = true;
// First destroy any sub-tasks
if(m_subTaskInternal)
{
m_subTaskInternal->Kill();
}
// Destroy the underlying std::coroutine_handle
m_coroHandle.destroy(); // This should only ever be called directly from this one place
m_coroHandle = nullptr;
m_taskReadyFn = nullptr; // Clear out the ready function
m_internalState = eInternalState::Destroyed;
}
}
// Done + can-resume status
void SetReadyFunction(const tTaskReadyFn& in_taskReadyFn)
{
m_taskReadyFn = in_taskReadyFn;
}
bool CanResume() const
{
if(IsDone())
{
return false;
}
if(m_subTaskInternal)
{
bool canResume = m_subTaskInternal->CanResume();
return canResume;
}
bool isReady = !m_taskReadyFn || m_taskReadyFn();
return isReady;
}
bool IsDone() const
{
return m_isDone;
}
bool m_isDone = false;
// Internal state
enum class eInternalState
{
Idle,
Resuming,
Destroyed,
};
eInternalState m_internalState = eInternalState::Idle;
// Task ready condition (when awaiting a TFunction<bool>)
tTaskReadyFn m_taskReadyFn;
#if SQUID_USE_EXCEPTIONS
// Exceptions
std::exception_ptr m_exception = nullptr;
bool m_isExceptionSet = false;
#endif //SQUID_USE_EXCEPTIONS
// Sub-task
TSharedPtr<TaskInternalBase> m_subTaskInternal;
// Reference-counting (determines underlying std::coroutine_handle lifetime, not lifetime of this internal task)
void AddLogicalRef()
{
++m_refCount;
}
void RemoveLogicalRef()
{
--m_refCount;
if(m_refCount == 0)
{
Kill();
}
}
int32_t m_refCount = 0; // Number of (strong) non-weak tasks referencing the internal task
// C++ std::coroutine_handle
std::coroutine_handle<> m_coroHandle;
// Stop request
bool m_isStopRequested = false;
TArray<TWeakPtr<TaskInternalBase>> m_stopTasks;
#if SQUID_ENABLE_TASK_DEBUG
// Debug Data
const char* m_debugName = "[unnamed task]";
TFunction<FString()> m_debugDataFn;
#endif //SQUID_ENABLE_TASK_DEBUG
};
//--- TaskInternal ---//
template <typename tRet>
class TaskInternal : public TaskInternalBase
{
public:
using promise_type = TaskPromise<tRet>;
TaskInternal(std::coroutine_handle<promise_type> in_handle)
: TaskInternalBase(in_handle)
{
auto& promisePtr = in_handle.promise();
promisePtr.SetInternalTask(this);
}
#if SQUID_USE_EXCEPTIONS
void SetUnhandledException(std::exception_ptr in_exception)
{
m_retValState = eTaskRetValState::Orphaned; // Return value can never be set if there was an unhandled exception
InternalSetUnhandledException(in_exception);
}
#endif //SQUID_USE_EXCEPTIONS
void SetReturnValue(const tRet& in_retVal)
{
tRet retVal = in_retVal;
SetReturnValue(MoveTemp(retVal));
}
void SetReturnValue(tRet&& in_retVal)
{
if(m_retValState == eTaskRetValState::Unset)
{
m_retVal = MoveTemp(in_retVal);
m_retValState = eTaskRetValState::Set;
return;
}
// These conditions should (logically) never be met, but they are included in case future changes violate that constraint
SQUID_RUNTIME_CHECK(m_retValState != eTaskRetValState::Set, "Attempted to set a task's return value when it was already set");
SQUID_RUNTIME_CHECK(m_retValState != eTaskRetValState::Taken, "Attempted to set a task's return value after it was already taken");
SQUID_RUNTIME_CHECK(m_retValState != eTaskRetValState::Orphaned, "Attempted to set a task's return value after it was orphaned");
}
TOptional<tRet> TakeReturnValue()
{
// If the value has been set, mark it as taken and move-return the value
if(m_retValState == eTaskRetValState::Set)
{
m_retValState = eTaskRetValState::Taken;
return MoveTemp(m_retVal);
}
// If the value was not set, return an unset optional (checking that it was neither taken nor orphaned)
SQUID_RUNTIME_CHECK(m_retValState != eTaskRetValState::Taken, "Attempted to take a task's return value after it was already successfully taken");
SQUID_RUNTIME_CHECK(m_retValState != eTaskRetValState::Orphaned, "Attempted to take a task's return value that will never be set (task ended prematurely)");
return {};
}
void OnTaskPromiseDestroyed()
{
// Mark the return value as orphaned if it was never set
m_retValState = eTaskRetValState::Orphaned;
}
private:
// Internal state
enum class eTaskRetValState
{
Unset, // Has not yet been set
Set, // Has been set and can be taken
Taken, // Has been taken and can no longer be taken
Orphaned, // Will never be set because the TaskPromise has been destroyed
};
eTaskRetValState m_retValState = eTaskRetValState::Unset; // Initially unset
TOptional<tRet> m_retVal;
};
template <>
class TaskInternal<void> : public TaskInternalBase
{
public:
using promise_type = TaskPromise<void>;
TaskInternal(std::coroutine_handle<promise_type> in_handle)
: TaskInternalBase(in_handle)
{
auto& promisePtr = in_handle.promise();
promisePtr.SetInternalTask(this);
}
#if SQUID_USE_EXCEPTIONS
void SetUnhandledException(std::exception_ptr in_exception)
{
InternalSetUnhandledException(in_exception);
}
#endif //SQUID_USE_EXCEPTIONS
void TakeReturnValue() // This function is an intentional no-op, to simplify certain templated function implementations
{
}
void OnTaskPromiseDestroyed()
{
}
};

View File

@ -0,0 +1,236 @@
#pragma once
//--- User configuration header ---//
#include "../TasksConfig.h"
// Namespace macros (enabled/disabled via SQUID_ENABLE_NAMESPACE)
#if SQUID_ENABLE_NAMESPACE
#define NAMESPACE_SQUID_BEGIN namespace Squid {
#define NAMESPACE_SQUID_END }
#define NAMESPACE_SQUID Squid
#else
#define NAMESPACE_SQUID_BEGIN
#define NAMESPACE_SQUID_END
#define NAMESPACE_SQUID
namespace Squid {} // Convenience to allow 'using namespace Squid' even when namespace is disabled
#endif
// Exception macros (to support environments with exceptions disabled)
#if SQUID_USE_EXCEPTIONS && (defined(__cpp_exceptions) || defined(__EXCEPTIONS))
#include <stdexcept>
#define SQUID_THROW(exception, errStr) throw exception;
#define SQUID_RUNTIME_ERROR(errStr) throw std::runtime_error(errStr);
#define SQUID_RUNTIME_CHECK(condition, errStr) if(!(condition)) throw std::runtime_error(errStr);
#else
#include <cassert>
#define SQUID_THROW(exception, errStr) assert(false && errStr);
#define SQUID_RUNTIME_ERROR(errStr) assert(false && errStr);
#define SQUID_RUNTIME_CHECK(condition, errStr) assert((condition) && errStr);
#endif //__cpp_exceptions
// Time Interface
NAMESPACE_SQUID_BEGIN
#if SQUID_ENABLE_DOUBLE_PRECISION_TIME
using tTaskTime = double;
#else
using tTaskTime = float; // Defines time units for use with the Task system
#endif //SQUID_ENABLE_DOUBLE_PRECISION_TIME
NAMESPACE_SQUID_END
// Coroutine de-optimization macros [DEPRECATED]
#ifdef _MSC_VER
#if _MSC_VER >= 1920
// Newer versions of Visual Studio (>= VS2019) compile coroutines correctly
#define COROUTINE_OPTIMIZE_OFF
#define COROUTINE_OPTIMIZE_ON
#else
// Older versions of Visual Studio had code generation bugs when optimizing coroutines (they would compile, but have incorrect runtime results)
#define COROUTINE_OPTIMIZE_OFF __pragma(optimize("", off))
#define COROUTINE_OPTIMIZE_ON __pragma(optimize("", on))
#endif // _MSC_VER >= 1920
#else
// The Clang compiler has sometimes crashed when optimizing/inlining certain coroutines, so this macro can be used to disable inlining
#define COROUTINE_OPTIMIZE_OFF _Pragma("clang optimize off")
#define COROUTINE_OPTIMIZE_ON _Pragma("clang optimize on")
#endif
// False type for use in static_assert() [static_assert(false, ...) -> static_assert(static_false<T>, ...)]
template<typename T>
struct static_false : std::false_type
{
};
// Determine C++ Language Version
#if defined(_MSVC_LANG)
#define CPP_LANGUAGE_VERSION _MSVC_LANG
#elif defined(__cplusplus)
#define CPP_LANGUAGE_VERSION __cplusplus
#else
#define CPP_LANGUAGE_VERSION 0L
#endif
#if CPP_LANGUAGE_VERSION > 201703L // C++20 or higher
#define HAS_CXX17 1
#define HAS_CXX20 1
#elif CPP_LANGUAGE_VERSION > 201402L // C++17 or higher
#define HAS_CXX17 1
#define HAS_CXX20 0
#elif CPP_LANGUAGE_VERSION > 201103L // C++14 or higher
#define HAS_CXX17 0
#define HAS_CXX20 0
#else // C++11 or lower
#error Squid::Tasks requires C++14 or higher
#define HAS_CXX17 0
#define HAS_CXX20 0
#endif
#undef CPP_LANGUAGE_VERSION
// C++20 Compatibility (std::coroutine)
#if HAS_CXX20 || (defined(_MSVC_LANG) && defined(__cpp_lib_coroutine)) // Standard coroutines
#include <coroutine>
#define SQUID_EXPERIMENTAL_COROUTINES 0
#else // Experimental coroutines
#if defined(__clang__) && defined(_STL_COMPILER_PREPROCESSOR)
// HACK: Some distributions of clang don't have a <experimental/coroutine> header. We only need a few symbols, so just define them ourselves
namespace std {
namespace experimental {
inline namespace coroutines_v1 {
template <typename R, typename...> struct coroutine_traits {
using promise_type = typename R::promise_type;
};
template <typename Promise = void> struct coroutine_handle;
template <> struct coroutine_handle<void> {
static coroutine_handle from_address(void* addr) noexcept {
coroutine_handle me;
me.ptr = addr;
return me;
}
void operator()() { resume(); }
void* address() const { return ptr; }
void resume() const { __builtin_coro_resume(ptr); }
void destroy() const { __builtin_coro_destroy(ptr); }
bool done() const { return __builtin_coro_done(ptr); }
coroutine_handle& operator=(decltype(nullptr)) {
ptr = nullptr;
return *this;
}
coroutine_handle(decltype(nullptr)) : ptr(nullptr) {}
coroutine_handle() : ptr(nullptr) {}
// void reset() { ptr = nullptr; } // add to P0057?
explicit operator bool() const { return ptr; }
protected:
void* ptr;
};
template <typename Promise> struct coroutine_handle : coroutine_handle<> {
using coroutine_handle<>::operator=;
static coroutine_handle from_address(void* addr) noexcept {
coroutine_handle me;
me.ptr = addr;
return me;
}
Promise& promise() const {
return *reinterpret_cast<Promise*>(
__builtin_coro_promise(ptr, alignof(Promise), false));
}
static coroutine_handle from_promise(Promise& promise) {
coroutine_handle p;
p.ptr = __builtin_coro_promise(&promise, alignof(Promise), true);
return p;
}
};
template <typename _PromiseT>
bool operator==(coroutine_handle<_PromiseT> const& _Left,
coroutine_handle<_PromiseT> const& _Right) noexcept
{
return _Left.address() == _Right.address();
}
template <typename _PromiseT>
bool operator!=(coroutine_handle<_PromiseT> const& _Left,
coroutine_handle<_PromiseT> const& _Right) noexcept
{
return !(_Left == _Right);
}
struct suspend_always {
bool await_ready() noexcept { return false; }
void await_suspend(coroutine_handle<>) noexcept {}
void await_resume() noexcept {}
};
struct suspend_never {
bool await_ready() noexcept { return true; }
void await_suspend(coroutine_handle<>) noexcept {}
void await_resume() noexcept {}
};
}
}
}
#else
#include <experimental/coroutine>
#endif
namespace std // Alias experimental coroutine symbols into std namespace
{
template <class _Promise = void>
using coroutine_handle = experimental::coroutine_handle<_Promise>;
using suspend_never = experimental::suspend_never;
using suspend_always = experimental::suspend_always;
};
#define SQUID_EXPERIMENTAL_COROUTINES 1
#endif
// Determine whether our tasks need the member function "unhandled_exception()" defined or not
#if defined(_MSC_VER)
// MSVC's rules for exceptions differ between standard + experimental coroutines
#if SQUID_EXPERIMENTAL_COROUTINES
// If exceptions are enabled, we must define unhandled_exception()
#if defined(__cpp_exceptions) && __cpp_exceptions == 199711
#define SQUID_NEEDS_UNHANDLED_EXCEPTION 1
#else
#define SQUID_NEEDS_UNHANDLED_EXCEPTION 0
#endif
#else
// If we're using VS16.11 or newer -- or older than 16.10, we have one set of rules for standard coroutines
#if _MSC_FULL_VER >= 192930133L || _MSC_VER < 1429L
#define SQUID_NEEDS_UNHANDLED_EXCEPTION 1
#else
#if defined(__cpp_exceptions) && __cpp_exceptions == 199711
#define SQUID_NEEDS_UNHANDLED_EXCEPTION 1
#else
// 16.10 has a bug with their standard coroutine implementation that creates a set of contradicting requirements
// https://developercommunity.visualstudio.com/t/coroutine-uses-promise_type::unhandled_e/1374530
#error Visual Studio 16.10 has a compiler bug that prevents all coroutines from compiling when exceptions are disabled and using standard C++20 coroutines or /await:strict. Please either upgrade your version of Visual Studio, or use the experimental /await flag, or enable exceptions.
#endif
#endif
#endif
#else
// Clang always requires unhandled_exception() to be defined
#define SQUID_NEEDS_UNHANDLED_EXCEPTION 1
#endif
// C++17 Compatibility ([[nodiscard]])
#if !defined(SQUID_NODISCARD) && defined(__has_cpp_attribute)
#if __has_cpp_attribute(nodiscard)
#define SQUID_NODISCARD [[nodiscard]]
#endif
#endif
#ifndef SQUID_NODISCARD
#define SQUID_NODISCARD
#endif
#undef HAS_CXX17
#undef HAS_CXX20
// Include UE core headers
#include "CoreMinimal.h"
#include "Engine/World.h"
#include "Engine/Engine.h"
#include "Async/Future.h"

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,331 @@
#pragma once
/// @defgroup TaskFSM Task FSM
/// @brief Finite state machine that implements states using task factories
/// @{
///
/// Full documentation of the TaskFSM system coming soon!
#include "Task.h"
NAMESPACE_SQUID_BEGIN
class TaskFSM;
namespace FSM
{
// State ID wrapper
struct StateId
{
StateId() = default;
StateId(int32_t in_idx) : idx(in_idx) {}
StateId(size_t in_idx) : idx((int32_t)in_idx) {}
bool operator==(const StateId& other) const { return (other.idx == idx); }
bool operator!=(const StateId& other) const { return (other.idx != idx); }
bool IsValid() const { return idx != INT32_MAX; }
int32_t idx = INT32_MAX; // Default to invalid idx
};
// State transition debug data
struct TransitionDebugData
{
FSM::StateId oldStateId;
FString oldStateName;
FSM::StateId newStateId;
FString newStateName;
};
// State transition callback function
using tOnStateTransitionFn = TFunction<void()>;
#include "Private/TaskFSMPrivate.h" // Internal use only! Do not include elsewhere!
//--- State Handle ---//
template<class tStateInput, class tStateConstructorFn>
class StateHandle
{
using tPredicateRet = typename std::conditional<!std::is_void<tStateInput>::value, TOptional<tStateInput>, bool>::type;
using tPredicateFn = TFunction<tPredicateRet()>;
public:
StateHandle(StateHandle&& in_other) = default;
StateHandle& operator=(StateHandle&& in_other) = default;
StateId GetId() const //< Get the ID of this state
{
return m_state ? m_state->idx : StateId{};
}
// SFINAE Template Declaration Macros (#defines)
/// @cond
#define NONVOID_ONLY_WITH_PREDICATE template <class tPredicateFn, typename tPayload = tStateInput, typename std::enable_if_t<!std::is_void<tPayload>::value>* = nullptr>
#define VOID_ONLY_WITH_PREDICATE template <class tPredicateFn, typename tPayload = tStateInput, typename std::enable_if_t<std::is_void<tPayload>::value>* = nullptr>
#define NONVOID_ONLY template <typename tPayload = tStateInput, typename std::enable_if_t<!std::is_void<tPayload>::value && !std::is_convertible<tPayload, tPredicateFn>::value>* = nullptr>
#define VOID_ONLY template <typename tPayload = tStateInput, typename std::enable_if_t<std::is_void<tPayload>::value>* = nullptr>
#define PREDICATE_ONLY template <typename tPredicateFn, typename std::enable_if_t<!std::is_convertible<tStateInput, tPredicateFn>::value>* = nullptr>
/// @endcond
// Link methods
VOID_ONLY LinkHandle Link() //< Empty predicate link (always follow link)
{
return _InternalLink([] { return true; }, LinkHandle::eType::Normal);
}
NONVOID_ONLY LinkHandle Link(tPayload in_payload) //< Empty predicate link w/ payload (always follow link, using provided payload)
{
return _InternalLink([payload = MoveTemp(in_payload)]() -> tPredicateRet { return payload; }, LinkHandle::eType::Normal);
}
PREDICATE_ONLY LinkHandle Link(tPredicateFn in_predicate) //< Predicate link w/ implicit payload (follow link when predicate returns a value; use return value as payload)
{
return _InternalLink(in_predicate, LinkHandle::eType::Normal);
}
NONVOID_ONLY_WITH_PREDICATE LinkHandle Link(tPredicateFn in_predicate, tPayload in_payload) //< Predicate link w/ explicit payload (follow link when predicate returns true; use provided payload)
{
return _InternalLink(in_predicate, MoveTemp(in_payload), LinkHandle::eType::Normal);
}
// OnCompleteLink methods
VOID_ONLY LinkHandle OnCompleteLink() //< Empty predicate link (always follow link)
{
return _InternalLink([] { return true; }, LinkHandle::eType::OnComplete);
}
NONVOID_ONLY LinkHandle OnCompleteLink(tPayload in_payload) //< Empty predicate link w/ payload (always follow link, using provided payload)
{
return _InternalLink([payload = MoveTemp(in_payload)]() -> tPredicateRet { return payload; }, LinkHandle::eType::OnComplete);
}
PREDICATE_ONLY LinkHandle OnCompleteLink(tPredicateFn in_predicate) //< Predicate link w/ implicit payload (follow link when predicate returns a value; use return value as payload)
{
return _InternalLink(in_predicate, LinkHandle::eType::OnComplete, true);
}
NONVOID_ONLY_WITH_PREDICATE LinkHandle OnCompleteLink(tPredicateFn in_predicate, tPayload in_payload) //< Predicate link w/ explicit payload (follow link when predicate returns true; use provided payload)
{
return _InternalLink(in_predicate, MoveTemp(in_payload), LinkHandle::eType::OnComplete, true);
}
private:
friend class ::TaskFSM;
StateHandle() = delete;
StateHandle(TSharedPtr<State<tStateInput, tStateConstructorFn>> InStatePtr)
: m_state(InStatePtr)
{
}
StateHandle(const StateHandle& Other) = delete;
StateHandle& operator=(const StateHandle& Other) = delete;
// Internal link function implementations
VOID_ONLY_WITH_PREDICATE LinkHandle _InternalLink(tPredicateFn in_predicate, LinkHandle::eType in_linkType, bool in_isConditional = false) // bool-returning predicate
{
static_assert(std::is_same<bool, decltype(in_predicate())>::value, "This link requires a predicate function returning bool");
TSharedPtr<LinkBase> link = MakeShared<FSM::Link<tStateInput, tStateConstructorFn, tPredicateFn>>(m_state, in_predicate);
return LinkHandle(link, in_linkType, in_isConditional);
}
NONVOID_ONLY_WITH_PREDICATE LinkHandle _InternalLink(tPredicateFn in_predicate, LinkHandle::eType in_linkType, bool in_isConditional = false) // optional-returning predicate
{
static_assert(std::is_same<TOptional<tStateInput>, decltype(in_predicate())>::value, "This link requires a predicate function returning TOptional<tStateInput>");
TSharedPtr<LinkBase> link = MakeShared<FSM::Link<tStateInput, tStateConstructorFn, tPredicateFn>>(m_state, in_predicate);
return LinkHandle(link, in_linkType, in_isConditional);
}
NONVOID_ONLY_WITH_PREDICATE LinkHandle _InternalLink(tPredicateFn in_predicate, tPayload in_payload, LinkHandle::eType in_linkType, bool in_isConditional = false) // bool-returning predicate w/ fixed payload
{
static_assert(std::is_same<bool, decltype(in_predicate())>::value, "This link requires a predicate function returning bool");
auto predicate = [in_predicate, in_payload]() -> TOptional<tStateInput>
{
return in_predicate() ? TOptional<tStateInput>(in_payload) : TOptional<tStateInput>{};
};
return _InternalLink(predicate, in_linkType, in_isConditional);
}
// SFINAE Template Declaration Macros (#undefs)
#undef NONVOID_ONLY_WITH_PREDICATE
#undef VOID_ONLY_WITH_PREDICATE
#undef NONVOID_ONLY
#undef VOID_ONLY
#undef PREDICATE_ONLY
TSharedPtr<State<tStateInput, tStateConstructorFn>> m_state; // Internal state object
};
} // namespace FSM
using StateId = FSM::StateId;
template<class tStateInput, class tStateConstructorFn>
using StateHandle = FSM::StateHandle<tStateInput, tStateConstructorFn>;
using TransitionDebugData = FSM::TransitionDebugData;
using tOnStateTransitionFn = FSM::tOnStateTransitionFn;
//--- TaskFSM ---//
class TaskFSM
{
public:
using tOnStateTransitionFn = TFunction<void()>;
using tDebugStateTransitionFn = TFunction<void(TransitionDebugData)>;
// Create a new FSM state [fancy param-deducing version (hopefully) coming soon!]
template<typename tStateConstructorFn>
auto State(FString in_name, tStateConstructorFn in_stateCtorFn)
{
typedef FSM::function_traits<tStateConstructorFn> tFnTraits;
using tStateInput = typename tFnTraits::tArg;
const FSM::StateId newStateId = m_states.Num();
m_states.Add(InternalStateData(in_name));
auto state = MakeShared<FSM::State<tStateInput, tStateConstructorFn>>(MoveTemp(in_stateCtorFn), newStateId, in_name);
return FSM::StateHandle<tStateInput, tStateConstructorFn>{ state };
}
// Create a new FSM exit state (immediately terminates the FSM when executed)
FSM::StateHandle<void, void> State(FString in_name)
{
const FSM::StateId newStateId = m_states.Num();
m_states.Add(InternalStateData(in_name));
m_exitStates.Add(newStateId);
auto state = MakeShared<FSM::State<void, void>>(newStateId, in_name);
return FSM::StateHandle<void, void>{ state };
}
// Define the initial entry links into the state machine
void EntryLinks(TArray<FSM::LinkHandle> in_entryLinks);
// Define all outgoing links from a given state (may only be called once per state)
template<class tStateInput, class tStateConstructorFn>
void StateLinks(const FSM::StateHandle<tStateInput, tStateConstructorFn>& in_originState, TArray<FSM::LinkHandle> in_outgoingLinks);
// Begins execution of the state machine (returns id of final exit state)
Task<FSM::StateId> Run(tOnStateTransitionFn in_onTransitionFn = {}, tDebugStateTransitionFn in_debugStateTransitionFn = {}) const;
private:
// Evaluates all possible outgoing links from the current state, returning the first valid transition (if any transitions are valid)
TOptional<FSM::TransitionEvent> EvaluateLinks(FSM::StateId in_curStateId, bool in_isCurrentStateComplete, const tOnStateTransitionFn& in_onTransitionFn) const;
// Internal state
struct InternalStateData
{
InternalStateData(FString in_debugName)
: debugName(in_debugName)
{
}
TArray<FSM::LinkHandle> outgoingLinks;
FString debugName;
};
TArray<InternalStateData> m_states;
TArray<FSM::LinkHandle> m_entryLinks;
TArray<FSM::StateId> m_exitStates;
};
/// @} end of group TaskFSM
//--- TaskFSM Methods ---//
template<class tStateInput, class tStateConstructorFn>
void TaskFSM::StateLinks(const FSM::StateHandle<tStateInput, tStateConstructorFn>& in_originState, TArray<FSM::LinkHandle> in_outgoingLinks)
{
const int32_t stateIdx = in_originState.m_state->stateId.idx;
SQUID_RUNTIME_CHECK(m_states[stateIdx].outgoingLinks.Num() == 0, "Cannot set outgoing links more than once for each state");
// Validate that there are exactly 0 or 1 unconditional OnComplete links (there may be any number of other OnComplete links, but only one with no condition)
int32_t numOnCompleteLinks = 0;
int32_t numOnCompleteLinks_Unconditional = 0;
for(const FSM::LinkHandle& link : in_outgoingLinks)
{
if(link.IsOnCompleteLink())
{
SQUID_RUNTIME_CHECK(numOnCompleteLinks_Unconditional == 0, "Cannot call OnCompleteLink() after calling OnCompleteLink() with no conditions (unreachable link)");
++numOnCompleteLinks;
if(!link.HasCondition())
{
numOnCompleteLinks_Unconditional++;
}
}
}
SQUID_RUNTIME_CHECK(numOnCompleteLinks == 0 || numOnCompleteLinks_Unconditional > 0, "More than one unconditional OnCompleteLink() was set");
// Set the outgoing links for the origin state
m_states[stateIdx].outgoingLinks = MoveTemp(in_outgoingLinks);
}
inline void TaskFSM::EntryLinks(TArray<FSM::LinkHandle> in_entryLinks)
{
// Validate to ensure there are no OnComplete links set as entry links
int32_t numOnCompleteLinks = 0;
for(const FSM::LinkHandle& link : in_entryLinks)
{
if(link.IsOnCompleteLink())
{
++numOnCompleteLinks;
}
}
SQUID_RUNTIME_CHECK(numOnCompleteLinks == 0, "EntryLinks() list may not contain any OnCompleteLink() links");
// Set the entry links list for this FSM
m_entryLinks = MoveTemp(in_entryLinks);
}
inline TOptional<FSM::TransitionEvent> TaskFSM::EvaluateLinks(FSM::StateId in_curStateId, bool in_isCurrentStateComplete, const tOnStateTransitionFn& in_onTransitionFn) const
{
// Determine whether to use entry links or state-specific outgoing links
const TArray<FSM::LinkHandle>& links = (in_curStateId.idx < m_states.Num()) ? m_states[in_curStateId.idx].outgoingLinks : m_entryLinks;
// Find the first valid transition from the current state
for(const FSM::LinkHandle& link : links)
{
if(!link.IsOnCompleteLink() || in_isCurrentStateComplete) // Skip link evaluation check for OnComplete links unless current state is complete
{
if(auto result = link.EvaluateLink(in_onTransitionFn)) // Check if the transition to this state is valid
{
return result;
}
}
}
return {}; // No valid transition was found
}
inline Task<FSM::StateId> TaskFSM::Run(tOnStateTransitionFn in_onTransitionFn, tDebugStateTransitionFn in_debugStateTransitionFn) const
{
// Task-local variables
FSM::StateId curStateId; // The current state's ID
Task<> task; // The current state's task
// Custom debug task name logic
TASK_NAME(__FUNCTION__, [this, &curStateId, &task]
{
const auto stateName = m_states.IsValidIndex(curStateId.idx) ? m_states[curStateId.idx].debugName : "";
return FString::Printf(TEXT("%s -- %s"), *stateName, *task.GetDebugStack());
});
// Debug state transition lambda
auto DebugStateTransition = [this, in_debugStateTransitionFn](FSM::StateId in_oldStateId, FSM::StateId in_newStateId) {
if(in_debugStateTransitionFn)
{
FString oldStateName = in_oldStateId.IsValid() ? m_states[in_oldStateId.idx].debugName : FString("<ENTRY>");
FString newStateName = m_states[in_newStateId.idx].debugName;
in_debugStateTransitionFn({ in_oldStateId, MoveTemp(oldStateName), in_newStateId, MoveTemp(newStateName) });
}
};
// Main FSM loop
while(true)
{
// Evaluate links, checking for a valid transition
if(TOptional<FSM::TransitionEvent> transition = EvaluateLinks(curStateId, task.IsDone(), in_onTransitionFn))
{
auto newStateId = transition->newStateId;
DebugStateTransition(curStateId, newStateId); // Call state-transition debug function
// If the transition is to an exit state, return that state ID (terminating the FSM)
if(m_exitStates.Contains(newStateId.idx))
{
co_return newStateId;
}
SQUID_RUNTIME_CHECK(newStateId.idx < m_states.Num(), "It should be logically impossible to get an invalid state to this point");
// Begin running new state (implicitly killing old state)
curStateId = newStateId;
co_await RemoveStopTask(task);
task = MoveTemp(transition->newTask); // NOTE: Initial call to Resume() happens below
co_await AddStopTask(task);
}
// Resume current state
task.Resume();
// Suspend until next frame
co_await Suspend();
}
}
NAMESPACE_SQUID_END

View File

@ -0,0 +1,215 @@
#pragma once
/// @defgroup TaskManager Task Manager
/// @brief Manager that runs and resumes a collection of tasks.
/// @{
///
/// A TaskManager is a simple manager class that holds an ordered list of tasks and resumes them whenever it is updated.
///
/// Running Tasks
/// -------------
/// There are two primary ways to run tasks on a task manager.
///
/// The first method (running an "unmanaged task") is to pass a task into @ref TaskManager::Run(). This will move the task
/// into the task manager and return a @ref TaskHandle that can be used to observe and manage the lifetime of the task (as well
/// as potentially take a return value after the task finishes). With unmanaged tasks, the task manager only holds a weak
/// reference to the task, meaning that the @ref TaskHandle returned by @ref TaskManager::Run() is the only remaining strong
/// reference to the task. Because of this, the caller is entirely responsible for managing the lifetime of the task.
///
/// The second method (running a "managed task") is to pass a task into @ref TaskManager::RunManaged(). Like
/// @ref TaskManager::Run(), this will move the task into the task manager and return a @ref WeakTaskHandle that can be used to
/// observe the lifetime of the task (as well as manually kill it, if desired). Unlike unmanaged tasks, the task manager
/// stores a strong reference to the task. Because of this, that caller is not responsible for managing the lifetime of
/// the task. This difference in task ownership means that (unlike an unmanaged task) a managed task can be thought of as
/// a "fire-and-forget" task that will run until either it finishes or until something else explicitly kills it.
///
/// Order of Execution
/// ------------------
/// The ordering of task updates within a call to @ref TaskManager::Update() is stable, meaning that the first task that
/// is run on a task manager will remain the first to resume, no matter how many other tasks are run on the task manager
/// (or terminate) in the meantime.
///
/// Integration into Actor Classes
/// ------------------------------
/// Consider the following example of a TaskManager that has been integrated into a TaskActor base class:
///
/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
///
/// class TaskActor : public Actor
/// {
/// public:
/// virtual void OnInitialize() override // Automatically called when this enemy enters the scene
/// {
/// Actor::OnInitialize(); // Call the base Actor function
/// m_taskMgr.RunManaged(ManageActor()); // Run main actor task as a fire-and-forget "managed task"
/// }
///
/// virtual void Tick(float in_dt) override // Automatically called every frame
/// {
/// Actor::Tick(in_dt); // Call the base Actor function
/// m_taskMgr.Update(); // Resume all active tasks once per tick
/// }
///
/// virtual void OnDestroy() override // Automatically called when this enemy leaves the scene
/// {
/// m_taskMgr.KillAllTasks(); // Kill all active tasks when we leave the scene
/// Actor::OnDestroy(); // Call the base Actor function
/// }
///
/// protected:
/// virtual Task<> ManageActor() // Overridden (in its entirety) by child classes
/// {
/// co_await WaitForever(); // Waits forever (doing nothing)
/// }
///
/// TaskManager m_taskMgr;
/// };
///
/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
///
/// In the above example, TaskManager is instantiated once per high-level actor. It is updated once per frame within
/// the Tick() method, and all its tasks are killed when it leaves the scene in OnDestroy(). Lastly, a single entry-point
/// coroutine is run as a managed task when the actor enters the scene. (The above is the conventional method of integration
/// into this style of game engine.)
///
/// Note that it is sometimes necessary to have multiple TaskManagers within a single actor. For example, if there are
/// multiple tick functions (such as one for pre-physics updates and one for post-physics updates), then instantiating
/// a second "post-physics" task manager may be desirable.
#include "Task.h"
NAMESPACE_SQUID_BEGIN
//--- TaskManager ---//
/// Manager that runs and resumes a collection of tasks.
class TaskManager
{
public:
~TaskManager() {} /// Destructor (disables copy/move construction + assignment)
/// @brief Run an unmanaged task
/// @details Run() return a @ref TaskHandle<> that holds a strong reference to the task. If there are ever no
/// strong references remaining to an unmanaged task, it will immediately be killed and removed from the manager.
template <typename tRet>
SQUID_NODISCARD TaskHandle<tRet> Run(Task<tRet>&& in_task)
{
// Run unmanaged task
TaskHandle<tRet> taskHandle = in_task;
WeakTask weakTask = MoveTemp(in_task);
RunWeakTask(MoveTemp(weakTask));
return taskHandle;
}
template <typename tRet>
SQUID_NODISCARD TaskHandle<tRet> Run(const Task<tRet>& in_task) /// @private Illegal copy implementation
{
static_assert(static_false<tRet>::value, "Cannot run an unmanaged task by copy (try Run(MoveTemp(task)))");
return {};
}
/// @brief Run a managed task
/// @details RunManaged() return a @ref WeakTaskHandle, meaning it can be used to run a "fire-and-forget" background
/// task in situations where it is not necessary to observe or control task lifetime.
template <typename tRet>
WeakTaskHandle RunManaged(Task<tRet>&& in_task)
{
// Run managed task
WeakTaskHandle weakTaskHandle = in_task;
m_strongRefs.Add(Run(MoveTemp(in_task)));
return weakTaskHandle;
}
template <typename tRet>
WeakTaskHandle RunManaged(const Task<tRet>& in_task) /// @private Illegal copy implementation
{
static_assert(static_false<tRet>::value, "Cannot run a managed task by copy (try RunManaged(MoveTemp(task)))");
return {};
}
/// @brief Run a weak task
/// @details RunWeakTask() runs a WeakTask. The caller is assumed to have already created a strong TaskHandle<> that
/// references the WeakTask, thus keeping it from being killed. When the last strong reference to the WeakTask is
/// destroyed, the task will immediately be killed and removed from the manager.
void RunWeakTask(WeakTask&& in_task)
{
// Run unmanaged task
m_tasks.Add(MoveTemp(in_task));
}
/// Call Task::Kill() on all tasks (managed + unmanaged)
void KillAllTasks()
{
m_tasks.Reset(); // Destroying all the weak tasks implicitly destroys all internal tasks
// No need to call Kill() on each TaskHandle in m_strongRefs
m_strongRefs.Reset(); // Handles in the strong refs array only ever point to tasks in the now-cleared m_tasks array
}
/// @brief Issue a stop request using @ref Task::RequestStop() on all active tasks (managed and unmanaged)
/// @details Returns a new awaiter task that will wait until all those tasks have all terminated.
Task<> StopAllTasks()
{
// Request stop on all tasks
TArray<WeakTaskHandle> weakHandles;
for(auto& task : m_tasks)
{
task.RequestStop();
weakHandles.Add(task);
}
// Return a fence task that waits until all stopped tasks are complete
return [](TArray<WeakTaskHandle> in_weakHandles) -> Task<> {
TASK_NAME("StopAllTasks() Fence Task");
for(const auto& weakHandle : in_weakHandles)
{
co_await weakHandle; // Wait until task is complete
}
}(MoveTemp(weakHandles));
}
/// Call @ref Task::Resume() on all active tasks exactly once (managed + unmanaged)
void Update()
{
// Resume all tasks
int32 writeIdx = 0;
for(int32 readIdx = 0; readIdx < m_tasks.Num(); ++readIdx)
{
if(m_tasks[readIdx].Resume() != eTaskStatus::Done)
{
if(writeIdx != readIdx)
{
m_tasks[writeIdx] = MoveTemp(m_tasks[readIdx]);
}
++writeIdx;
}
}
m_tasks.SetNum(writeIdx);
// Prune strong tasks that are done
m_strongRefs.RemoveAllSwap([](const auto& in_taskHandle) { return in_taskHandle.IsDone(); });
}
/// Get a debug string containing a list of all active tasks
FString GetDebugString(TOptional<TaskDebugStackFormatter> in_formatter = {}) const
{
FString debugStr;
for(const auto& task : m_tasks)
{
if(!task.IsDone())
{
if(debugStr.Len())
{
debugStr += '\n';
}
debugStr += task.GetDebugStack(in_formatter);
}
}
return debugStr;
}
private:
TArray<WeakTask> m_tasks;
TArray<TaskHandle<>> m_strongRefs;
};
NAMESPACE_SQUID_END
///@} end of TaskManager group

View File

@ -0,0 +1,48 @@
#pragma once
// Squid::Tasks version (major.minor.patch)
#define SQUID_TASKS_VERSION_MAJOR 0
#define SQUID_TASKS_VERSION_MINOR 2
#define SQUID_TASKS_VERSION_PATCH 0
/// @defgroup Config Configuration
/// @brief Configuration settings for the Squid::Tasks library
/// @{
/// Enables Task debug names and callstack tracking via Task::GetDebugStack() and Task::GetDebugName()
#ifndef SQUID_ENABLE_TASK_DEBUG
#define SQUID_ENABLE_TASK_DEBUG 1
#endif
/// Switches time type (tTaskTime) from 32-bit single-precision floats to 64-bit double-precision floats
#ifndef SQUID_ENABLE_DOUBLE_PRECISION_TIME
#define SQUID_ENABLE_DOUBLE_PRECISION_TIME 0
#endif
/// Wraps a Squid:: namespace around all classes in the Squid::Tasks library
#ifndef SQUID_ENABLE_NAMESPACE
#define SQUID_ENABLE_NAMESPACE 0
#endif
/// Enables experimental (largely-untested) exception handling, and replaces all asserts with runtime_error exceptions
#ifndef SQUID_USE_EXCEPTIONS
#define SQUID_USE_EXCEPTIONS 0
#endif
/// Enables global time support(alleviating the need to specify a time stream for time - sensitive awaiters) [see @ref GetGlobalTime()]
#ifndef SQUID_ENABLE_GLOBAL_TIME
// ***************
// *** WARNING ***
// ***************
// It is generally inadvisable for game projects to define a global task time, as it assumes there is only a single time-stream.
// Within game projects, there is usually a "game time" and "real time", as well as others (such as "audio time", "unpaused time").
// Furthermore, in engines such as Unreal, a non-static world context object must be provided.
// To enable global task time, user must *also* define a GetGlobalTime() implementation (otherwise there will be a linker error)
#define SQUID_ENABLE_GLOBAL_TIME 0
#endif
/// @} end of addtogroup Config
//--- C++17/C++20 Compatibility ---//
#include "Private/TasksCommonPrivate.h"

View File

@ -0,0 +1,320 @@
#pragma once
/// @defgroup Tokens Token List
/// @brief Data structure for tracking decentralized state across multiple tasks.
/// @{
///
/// Token objects can be created using @ref TokenList::MakeToken(), returning a shared pointer to a new Token. This
/// new Token can then be added to the TokenList using @ref TokenList::AddToken(). @ref TokenList::TakeToken()
/// can be used to make + add a new token with a single function call.
///
/// Because TokenList uses weak pointers to track its elements, Token objects are logically removed from the list once
/// they are destroyed. As such, it is usually unnecessary to explicitly call @ref TokenList::RemoveToken() to remove a
/// Token from the list. Instead, it is idiomatic to consider the Token to be a sort of "scope guard" that will remove
/// itself from all TokenList objects when it leaves scope.
///
/// The TokenList class is included as part of Squid::Tasks to provide a simple mechanism for robustly sharing aribtrary
/// state between multiple tasks. Consider this example of a poison damage-over-time system:
/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
///
/// class Character : public Actor
/// {
/// public:
/// bool IsPoisoned() const
/// {
/// return m_poisonTokens; // Whether there are any live poison tokens
/// }
///
/// void OnPoisoned(float in_dps, float in_duration)
/// {
/// m_taskMgr.RunManaged(ManagePoisonInstance(in_dps, in_duration));
/// }
///
/// private:
/// TokenList<float> m_poisonTokens; // Token list indicating live poison damage
///
/// Task<> ManagePoisonInstance(float in_dps, float in_duration)
/// {
/// // Take a poison token and hold it for N seconds
/// auto poisonToken = m_poisonTokens.TakeToken(__FUNCTION__, in_dps);
/// co_await WaitSeconds(in_duration);
/// }
///
/// Task<> ManageCharacter() // Called once per frame
/// {
/// while(true)
/// {
/// float poisonDps = m_poisonTokens.GetMax(); // Get highest DPS poison instance
/// DealDamage(poisonDps * GetDT()); // Deal the actual poison damage
/// co_await Suspend();
/// }
/// }
/// };
///
/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
///
/// As the above example shows, this mechanism is well-suited for coroutines, as they can hold a Token across
/// multiple frames. Also note that Token objects can optionally hold data. The TokenList class has query functions
/// (e.g. GetMin()/GetMax()) that can be used to aggregate the data from the set of live tokens. This is used above
/// to quickly find the highest DPS poison instance.
#include <algorithm>
#include <numeric>
#include <vector>
#include <string>
//--- User configuration header ---//
#include "TasksConfig.h"
NAMESPACE_SQUID_BEGIN
template <typename T = void>
class TokenList;
/// @brief Handle to a TokenList element that stores a debug name
/// @details In most circumstances, name should be set to \ref __FUNCTION__ at the point of creation.
struct Token
{
Token(FString in_name)
: name(MoveTemp(in_name))
{
}
FString name; // Used for debug only
};
/// @brief Handle to a TokenList element that stores both a debug name and associated data
/// @details In most circumstances, name should be set to \c __FUNCTION__ at the point of creation.
template <typename tData>
struct DataToken
{
DataToken(FString in_name, tData in_data)
: name(MoveTemp(in_name))
, data(MoveTemp(in_data))
{
}
FString name; // Used for debug only
tData data;
};
/// Create a token with the specified debug name
inline TSharedPtr<Token> MakeToken(FString in_name)
{
return MakeShared<Token>(MoveTemp(in_name));
}
/// Create a token with the specified debug name and associated data
template <typename tData>
TSharedPtr<DataToken<tData>> MakeToken(FString in_name, tData in_data)
{
return MakeShared<DataToken<tData>>(MoveTemp(in_name), MoveTemp(in_data));
}
/// @brief Container for tracking decentralized state across multiple tasks. (See \ref Tokens for more info...)
/// @tparam T Type of data to associate with each Token in this container
template <typename T>
class TokenList
{
public:
/// Type of Token tracked by this container
using Token = typename std::conditional_t<std::is_void<T>::value, Token, DataToken<T>>;
/// Create a token with the specified debug name
template <typename U = T, typename std::enable_if_t<std::is_void<U>::value>* = nullptr>
static TSharedPtr<Token> MakeToken(FString in_name)
{
return MakeShared<Token>(MoveTemp(in_name));
}
/// Create a token with the specified debug name and associated data
template <typename U = T, typename std::enable_if_t<!std::is_void<U>::value>* = nullptr>
static TSharedPtr<Token> MakeToken(FString in_name, U in_data)
{
return MakeShared<Token>(MoveTemp(in_name), MoveTemp(in_data));
}
/// Create and add a token with the specified debug name
template <typename U = T, typename std::enable_if_t<std::is_void<U>::value>* = nullptr>
SQUID_NODISCARD TSharedPtr<Token> TakeToken(FString in_name)
{
return AddToken(MakeToken(MoveTemp(in_name)));
}
/// Create and add a token with the specified debug name and associated data
template <typename U = T, typename std::enable_if_t<!std::is_void<U>::value>* = nullptr>
SQUID_NODISCARD TSharedPtr<Token> TakeToken(FString in_name, U in_data)
{
return AddToken(MakeToken(MoveTemp(in_name), MoveTemp(in_data)));
}
/// Add an existing token to this container
TSharedPtr<Token> AddToken(TSharedPtr<Token> in_token)
{
SQUID_RUNTIME_CHECK(in_token, "Cannot add null token");
Sanitize();
m_tokens.AddUnique(in_token);
return in_token;
}
/// Explicitly remove a token from this container
void RemoveToken(TSharedPtr<Token> in_token)
{
// Find and remove the token
m_tokens.Remove(in_token);
}
/// Convenience conversion operator that calls HasTokens()
operator bool() const
{
return HasTokens();
}
/// Returns whether this container holds any live tokens
bool HasTokens() const
{
// Return true when holding any unexpired tokens
for(auto i = (int32_t)(m_tokens.Num() - 1); i >= 0; --i)
{
const auto& token = m_tokens[i];
if(token.IsValid())
{
return true;
}
m_tokens.Pop(); // Because the token is expired, we can safely remove it from the back
}
return false;
}
/// Returns an array of all live token data
TArray<T> GetTokenData() const
{
TArray<T> tokenData;
for(const auto& tokenWeak : m_tokens)
{
if(auto token = tokenWeak.Pin())
{
tokenData.Add(token->data);
}
}
return tokenData;
}
/// @name Data Queries
/// Methods for querying and aggregating the data from the set of live tokens.
/// @{
/// Returns associated data from the least-recently-added live token
TOptional<T> GetLeastRecent() const
{
Sanitize();
return m_tokens.Num() ? m_tokens[0].Pin()->data : TOptional<T>{};
}
/// Returns associated data from the most-recently-added live token
TOptional<T> GetMostRecent() const
{
Sanitize();
return m_tokens.Num() ? m_tokens.Last().Pin()->data : TOptional<T>{};
}
/// Returns smallest associated data from the set of live tokens
TOptional<T> GetMin() const
{
TOptional<T> ret;
SanitizeAndProcessData([&ret](const T& in_data) {
if(!ret || in_data < ret.GetValue())
{
ret = in_data;
}
});
return ret;
}
/// Returns largest associated data from the set of live tokens
TOptional<T> GetMax() const
{
TOptional<T> ret;
SanitizeAndProcessData([&ret](const T& in_data) {
if(!ret || in_data > ret.GetValue())
{
ret = in_data;
}
});
return ret;
}
/// Returns arithmetic mean of all associated data from the set of live tokens
TOptional<double> GetMean() const
{
TOptional<double> ret;
TOptional<double> total;
SanitizeAndProcessData([&total](const T& in_data) {
total = total.Get(0.0) + (double)in_data;
});
if(total)
{
ret = total.GetValue() / m_tokens.Num();
}
return ret;
}
/// Returns whether the set of live tokens contains at least one token associated with the specified data
template <typename U = T, typename std::enable_if_t<!std::is_void<U>::value>* = nullptr>
bool Contains(const U& in_searchData) const
{
bool containsData = false;
SanitizeAndProcessData([&in_searchData, &containsData](const T& in_data) {
if(in_searchData == in_data)
{
containsData = true;
}
});
return containsData;
}
///@} end of Data Queries
/// Returns a debug string containing a list of the debug names of all live tokens
FString GetDebugString() const
{
TArray<FString> tokenStrings;
for(auto token : m_tokens)
{
if(token.IsValid())
{
tokenStrings.Add(token.Pin()->name);
}
}
if(tokenStrings.Num())
{
return FString::Join(tokenStrings, TEXT("\n"));
}
return TEXT("[no tokens]");
}
private:
// Sanitation
void Sanitize() const
{
// Remove all invalid tokens
m_tokens.RemoveAll([](const Wp<Token>& in_token) { return !in_token.IsValid(); });
}
template <typename tFn>
void SanitizeAndProcessData(tFn in_dataFn) const
{
// Remove all invalid tokens while applying a processing function on each valid token
m_tokens.RemoveAll([&in_dataFn](const TWeakPtr<Token>& in_token) {
if(auto pinnedToken = in_token.Pin())
{
in_dataFn(pinnedToken->data);
return false;
}
return true;
});
}
// Token data
mutable TArray<TWeakPtr<Token>> m_tokens; // Mutable so we can remove expired tokens while converting bool
};
NAMESPACE_SQUID_END
///@} end of Tokens group

View File

@ -0,0 +1,7 @@
#pragma once
#include "SquidTasks/Task.h"
#include "SquidTasks/TaskManager.h"
#include "SquidTasks/TokenList.h"
#include "SquidTasks/FunctionGuard.h"
#include "SquidTasks/TaskFSM.h"

View File

@ -0,0 +1,17 @@
using UnrealBuildTool;
public class SquidTasks : ModuleRules
{
public SquidTasks(ReadOnlyTargetRules Target) : base(Target)
{
DefaultBuildSettings = BuildSettingsVersion.V2;
PublicDependencyModuleNames.AddRange(new string[] {
"Core",
"CoreUObject",
"Engine",
});
SharedPCHHeaderFile = "Public/SquidTasksSharedPCH.h";
}
}

View File

@ -0,0 +1,25 @@
{
"FileVersion": 1,
"Version": 1,
"VersionName": "1.0",
"FriendlyName": "SquidTasks",
"Description": "Giant Squid's Task Plugin",
"Category": "Other",
"CreatedBy": "Giant Squid",
"CreatedByURL": "",
"DocsURL": "",
"MarketplaceURL": "",
"SupportURL": "",
"EnabledByDefault": true,
"CanContainContent": true,
"IsBetaVersion": false,
"IsExperimentalVersion": false,
"Installed": false,
"Modules": [
{
"Name": "SquidTasks",
"Type": "Runtime",
"LoadingPhase": "Default"
},
]
}