paranim / pararules

A Nim rules engine
The Unlicense
142 stars 4 forks source link

Make code ORC Friendly? #3

Closed arunvickram closed 2 years ago

arunvickram commented 3 years ago

I was wondering if there was a way to make my pararules integration more ORC friendly? At the moment I can't really integrate it as part of the engine because I've set up my project to use ORC, and it won't let me access anything defined at the top level, including sessions and rules because it's unsafe and collected by the GC.

For reference, here is the file that uses paranim in my project:

import godot
import godotapi/spatial
import asyncdispatch
import pararules
import heapqueue
import source/combat/[battler, stats]
import source/party/skill
import options
import macros

type
  Id* = enum
    Arena,
  Attr* = enum
    CurrentTurn, NextTurn,
    # Stats, Skills,
    IsPlayerControlled,
    ActiveBattler
    # AllBattlers
  TurnQueue* = seq[Battler]
  # SkillSet = ref seq[Skill]
  # Battlers = ref seq[Battler]

proc pop(q: TurnQueue): Battler =
  q.pop()

schema Fact(Id, Attr):
  CurrentTurn: TurnQueue
  NextTurn: TurnQueue
  # Stats: Stats
  # Skills: SkillSet
  IsPlayerControlled: bool
  ActiveBattler: Battler
  # AllBattlers: Battlers

let rule1 =
  rule getCurrentBattler(Fact):
    what:
      (Arena, ActiveBattler, battler)
      (Arena, CurrentTurn, currentTurn, then = false)
    cond:
      battler == nil
    then:
      let currentBattler: Battler = currentTurn[0]
      session.insert(Arena, ActiveBattler, currentBattler)

var
  session = initSession(Fact, autoFire = false)
  initialSession = deepCopy(session)

session.add(rule1)

gdobj BattleArena of Spatial:
  signal battle_ends()
  signal victory()
  signal game_over()

  proc battleStart*() =
    session.add(rule1)
    discard

and here's the error that the compiler is throwing:

/Users/arun/RPG/src/source/combat/battle_arena.nim(54, 7) template/generic instantiation of `gdobj` from here
/Users/arun/RPG/src/source/combat/battle_arena.nim(61, 8) Error: 'battleStart' is not GC-safe as it accesses 'rule1' which is a global using GC'ed memory
     Error: Execution failed with exit code 256
        ... Command: /Users/arun/.nimble/bin/nim c --noNimblePath -d:NimblePkgVersion=0.1.0 --path:'/Users/arun/.nimble/pkgs/godot-#master' --path:/Users/arun/.nimble/pkgs/compiler-1.5.1 --path:/Users/arun/.nimble/pkgs/pararules-0.14.0 --path:/Users/arun/.nimble/pkgs/macroutils-1.2.0 -o:../_dlls/nim_mac.dylib ../src/stub

I stumbled upon this article, and it seems like I could theoretically use shared and guarded pointers, that would require getting the types for Session right in my code, which I haven't been able to do. Any ideas on how to proceed from here?

oakes commented 3 years ago

I have compiled my games with orc without any problems, but i guess this is an issue when interacting with godot. What do you mean by "getting the types for Session"?

Sessions and rules don't need to be defined at the top level. Is there a more local place where you could define them, if that is the problem?

Also are you sure the problem isn't deepCopy? I thought that was problematic with orc. Try using the second suggestion i made for removing all facts instead:

for fact in session.queryAll():
  session.retract(fact.id, Attr(fact.attr))
arunvickram commented 3 years ago

What I mean by "getting the types for Session" is writing the type annotations as such:

var session: Session[?] = initSession(Fact, autoFire = false)

I removed deepCopy entirely and it's still giving me that error. I defined it as a variable of the class I'm defining, but i'm still getting this:


import godot
import godotapi/spatial
import asyncdispatch
import pararules
import heapqueue
import source/combat/[battler, stats]
import source/party/skill
import options
import macros

type
  Id* = enum
    Arena,
  Attr* = enum
    CurrentTurn, NextTurn,
    # Stats, Skills,
    IsPlayerControlled,
    ActiveBattler
    # AllBattlers
  TurnQueue* = seq[Battler]
  # SkillSet = ref seq[Skill]
  # Battlers = ref seq[Battler]

proc pop(q: TurnQueue): Battler =
  q.pop()

schema Fact(Id, Attr):
  CurrentTurn: TurnQueue
  NextTurn: TurnQueue
  # Stats: Stats
  # Skills: SkillSet
  IsPlayerControlled: bool
  ActiveBattler: Battler
  # AllBattlers: Battlers

gdobj BattleArena of Spatial:
  signal battle_ends()
  signal victory()
  signal game_over()

  var session = initSession(Fact, autoFire = false)

  var rule1 =
    rule getCurrentBattler(Fact):
      what:
        (Arena, ActiveBattler, battler)
        (Arena, CurrentTurn, currentTurn, then = false)
      cond:
        battler == nil
      then:
        let currentBattler: Battler = currentTurn[0]
        session.insert(Arena, ActiveBattler, currentBattler)

  proc battleStart*() =
    self.session.add(self.rule1)
    discard

and here's the error:

/Users/arun/RPG/src/source/combat/battle_arena.nim(38, 7) template/generic instantiation of `gdobj` from here
/Users/arun/.nimble/pkgs/godot-#master/nim/godotmacros.nim(666, 37) Error: 'init' is not GC-safe as it accesses 'thenFn' which is a global using GC'ed memory
     Error: Execution failed with exit code 256
        ... Command: /Users/arun/.nimble/bin/nim c --noNimblePath -d:NimblePkgVersion=0.1.0 --path:'/Users/arun/.nimble/pkgs/godot-#master' --path:/Users/arun/.nimble/pkgs/compiler-1.5.1 --path:/Users/arun/.nimble/pkgs/pararules-0.14.0 --path:/Users/arun/.nimble/pkgs/macroutils-1.2.0 -o:../_dlls/nim_mac.dylib ../src/stub

I think it has something to do with the godot integration and the memory management model of Godot trying to access something from Nim that can be collected by the GC.

oakes commented 3 years ago

I think it will be Session[Fact, Table[string, Fact]], try that.

arunvickram commented 3 years ago

Hey sorry for the late response, I was caught up with work.

I'm getting:

     Error: Execution failed with exit code 256
        ... Command: /Users/arun/.nimble/bin/nim c --noNimblePath -d:NimblePkgVersion=0.1.0 --path:'/Users/arun/.nimble/pkgs/godot-#master' --path:/Users/arun/.nimble/pkgs/compiler-1.5.1 --path:/Users/arun/.nimble/pkgs/pararules-0.14.0 --path:/Users/arun/.nimble/pkgs/macroutils-1.2.0 -o:../_dlls/nim_mac.dylib ../src/stub
oakes commented 2 years ago

Let me know if this is still a problem; closing because this issue is a year old and pararules works well with orc.