MatchEngine: Difference between revisions

From Intrigues Wiki
(Created page with "= 🧠 Intrigues MatchEngine API Reference = == Overview == The <code>MatchEngine</code> is part of the Intrigues core system and provides a lightweight, asynchronous matchmaking mechanism between actors. It is designed to help characters find suitable partners based on rule-based logic and customizable conditions. ---- == πŸ”§ <code>CandidateFilter</code> (Optional) == <syntaxhighlight lang="c#"> IM.Instance.MatchEngine.CandidateFilter = (self, other) => ...; </syntax...")
Β 
No edit summary
Line 10: Line 10:
</syntaxhighlight>
</syntaxhighlight>


=== Description: ===
=== Description ===
<code>CandidateFilter</code> is a user-defined delegate that determines which actors are eligible to be evaluated as potential matches. It is executed '''before''' expensive rule-based compatibility checks (<code>IsCompatibleAsync</code>) are triggered.
<code>CandidateFilter</code> is a user-defined delegate that determines which actors are eligible to be evaluated as potential matches. It is executed '''before''' expensive rule-based compatibility checks (<code>IsCompatibleAsync</code>) are triggered.


=== Signature: ===
=== Signature ===
<syntaxhighlight lang="c#">
<syntaxhighlight lang="c#">
public Func<Actor, Actor, bool> CandidateFilter;
public Func<Actor, Actor, bool> CandidateFilter;
</syntaxhighlight>
</syntaxhighlight>


=== Purpose: ===
=== Purpose ===
To '''filter out clearly invalid candidates early''', improving performance and allowing customization of match logic (e.g., support for same-gender marriages, polygamy, or role-based restrictions).
To '''filter out clearly invalid candidates early''', improving performance and allowing customization of match logic (e.g., support for same-gender marriages, polygamy, or role-based restrictions).


=== Example: ===
=== Example ===
<syntaxhighlight lang="c#">
<syntaxhighlight lang="c#">
// Allow only opposite-gender, unmarried actors
// Allow only opposite-gender, unmarried actors
IM.Instance.MatchEngine.CandidateFilter = (self, other) =>
IM.Instance.MatchEngine.CandidateFilter = (self, other) =>
Β  Β  other.HasSpouse == false && other.Gender != self.Gender;
other.HasSpouse == false && other.Gender != self.Gender;


// Allow same-gender matches
// Allow same-gender matches
IM.Instance.MatchEngine.CandidateFilter = (self, other) =>
IM.Instance.MatchEngine.CandidateFilter = (self, other) =>
Β  Β  other.HasSpouse == false; // no gender check
other.HasSpouse == false; // no gender check
</syntaxhighlight>πŸ“ '''Note:''' This filter is typically set once during initialization (e.g., in <code>DemoManager.cs > Start()</code>), and applies globally across all match operations.
</syntaxhighlight>πŸ“ '''Note:''' This filter is typically set once during initialization (e.g., in <code>DemoManager.cs > Start()</code>), and applies globally across all match operations.


πŸ” <code>FindMatch(Actor actor, string rule)</code><syntaxhighlight lang="c#">
πŸ” <code>FindMatch(Actor actor, string rule)</code><syntaxhighlight lang="c#">
Line 36: Line 37:
</syntaxhighlight>
</syntaxhighlight>


=== Description: ===
=== Description ===
Scans all eligible actors to find a suitable match for the given <code>actor</code>, based on a specified rule (e.g., <code>"Love Rule"</code>). Returns the first actor that passes both the <code>CandidateFilter</code> (if any) and the <code>IsCompatibleAsync(...)</code> rule evaluation.
Scans all eligible actors to find a suitable match for the given <code>actor</code>, based on a specified rule (e.g., <code>"Love Rule"</code>). Returns the first actor that passes both the <code>CandidateFilter</code> (if any) and the <code>IsCompatibleAsync(...)</code> rule evaluation.


=== Signature: ===
=== Signature ===
<syntaxhighlight lang="c#">
<syntaxhighlight lang="c#">
public async Task<Actor> FindMatch(Actor actor, string rule)
public async Task<Actor> FindMatch(Actor actor, string rule)
</syntaxhighlight>
</syntaxhighlight>


=== Parameters: ===
=== Parameters ===
{| class="wikitable"
{| class="wikitable"
!Name
!Name
Line 59: Line 60:
|}
|}


=== Returns: ===
=== Returns ===


* <code>Actor</code> – A compatible partner, or <code>null</code> if no match is found
* <code>Actor</code> – A compatible partner, or <code>null</code> if no match is found


=== Example: ===
=== Example ===
<syntaxhighlight lang="c#">
<syntaxhighlight lang="c#">
private async void TryFindSpouse(Actor actor)
private async void TryFindSpouse(Actor actor)
Line 80: Line 81:
</syntaxhighlight>
</syntaxhighlight>


=== How It Works: ===
=== How It Works ===


# Filters all actors using <code>CandidateFilter</code> (if set)
# Filters all actors using <code>CandidateFilter</code> (if set)

Revision as of 21:45, 14 May 2025

🧠 Intrigues MatchEngine API Reference

Overview

The MatchEngine is part of the Intrigues core system and provides a lightweight, asynchronous matchmaking mechanism between actors. It is designed to help characters find suitable partners based on rule-based logic and customizable conditions.


πŸ”§ CandidateFilter (Optional)

IM.Instance.MatchEngine.CandidateFilter = (self, other) => ...;

Description

CandidateFilter is a user-defined delegate that determines which actors are eligible to be evaluated as potential matches. It is executed before expensive rule-based compatibility checks (IsCompatibleAsync) are triggered.

Signature

public Func<Actor, Actor, bool> CandidateFilter;

Purpose

To filter out clearly invalid candidates early, improving performance and allowing customization of match logic (e.g., support for same-gender marriages, polygamy, or role-based restrictions).

Example

// Allow only opposite-gender, unmarried actors
IM.Instance.MatchEngine.CandidateFilter = (self, other) =>
other.HasSpouse == false && other.Gender != self.Gender;

// Allow same-gender matches
IM.Instance.MatchEngine.CandidateFilter = (self, other) =>
other.HasSpouse == false; // no gender check

πŸ“ Note: This filter is typically set once during initialization (e.g., in DemoManager.cs > Start()), and applies globally across all match operations.


πŸ” FindMatch(Actor actor, string rule)

Actor matched = await IM.Instance.MatchEngine.FindMatch(actor, "Love Rule");

Description

Scans all eligible actors to find a suitable match for the given actor, based on a specified rule (e.g., "Love Rule"). Returns the first actor that passes both the CandidateFilter (if any) and the IsCompatibleAsync(...) rule evaluation.

Signature

public async Task<Actor> FindMatch(Actor actor, string rule)

Parameters

Name Type Description
actor Actor The actor who is seeking a match
rule string The name of the rule used to check compatibility

Returns

  • Actor – A compatible partner, or null if no match is found

Example

private async void TryFindSpouse(Actor actor)
{
    var match = await IM.Instance.MatchEngine.FindMatch(actor, "Love Rule");

    if (match != null)
    {
        actor.StartScheme("Love", match);
    }
    else
    {
        Debug.Log("No compatible match found.");
    }
}

How It Works

  1. Filters all actors using CandidateFilter (if set)
  2. Shuffles the list to avoid bias
  3. Iterates through each candidate and checks rule-based compatibility
  4. Returns the first matching actor

⚠️ Performance Tip

In large simulations (100+ actors), skipping CandidateFilter can cause significant slowdowns. Always define a lightweight CandidateFilter to minimize expensive async rule checks.


πŸ§ͺ Debugging Tip

To check how many candidates are being evaluated, you can log:

var count = IM.Actors.Count(p => MatchEngine.CandidateFilter(actor, p));
Debug.Log($"Evaluating {count} candidates for {actor.Name}");

βœ… Summary

Feature Purpose
CandidateFilter Filters actors before compatibility check
FindMatch Asynchronously finds the first compatible match
Fully async Doesn’t freeze the main thread
Customizable Users define matching conditions
Performant Filtering avoids unnecessary rule execution

For more advanced matching (e.g., scoring, top-N matches, or group dynamics), consider extending MatchEngine or integrating it with custom rule graphs.