Browse Source

Basic actor-based linked list implemented

ijon 1 year ago
parent
commit
2f9a24a212

+ 13 - 0
.gitignore

@@ -0,0 +1,13 @@
+*.pk[37]
+*.zip
+nocommit/*
+core.*
+zandronum-crash*
+!addons/*
+*.lnk
+*.backup?
+*.dbs
+*.bkp
+*.bak
+make.sh
+desktop.ini

+ 1 - 0
README.md

@@ -0,0 +1 @@
+lmao dice

+ 6 - 0
pk3/DECORATE.txt

@@ -0,0 +1,6 @@
+// Copyright © 2019 ijon <segfaultsamurai@gmail.com>
+// This work is free. You can redistribute it and/or modify it under the
+// terms of the Do What The Fuck You Want To Public License, Version 2,
+// as published by Sam Hocevar. See the LICENSE.txt file for more details.
+
+#include "decorate/boardSquares.txt"

+ 13 - 0
pk3/LICENSE.txt

@@ -0,0 +1,13 @@
+           DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
+                   Version 2, December 2004
+
+Copyright © 2004 Sam Hocevar <sam@hocevar.net>
+
+Everyone is permitted to copy and distribute verbatim or modified
+copies of this license document, and changing it is allowed as long
+as the name is changed.
+
+           DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
+  TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. You just DO WHAT THE FUCK YOU WANT TO.

+ 1 - 0
pk3/LOADACS.txt

@@ -0,0 +1 @@
+lmaodice

+ 41 - 0
pk3/acs/board_build.h

@@ -0,0 +1,41 @@
+// Copyright © 2019 ijon <segfaultsamurai@gmail.com>
+// This work is free. You can redistribute it and/or modify it under the
+// terms of the Do What The Fuck You Want To Public License, Version 2,
+// as published by Sam Hocevar. See the LICENSE.txt file for more details.
+
+script "DBoard_InitSquare" (void)
+{
+    int linkTID;
+    
+    if (DBoard_AllSquaresTID == -1)
+    {
+        DBoard_AllSquaresTID = ACS_NamedExecuteWithResult("DList_MakeLink", 0);
+        linkTID = DBoard_AllSquaresTID;
+    }
+    else
+    {
+        linkTID = ACS_NamedExecuteWithResult("DList_Append", DBoard_AllSquaresTID, 0);
+    }
+    
+    Log(s:"Square count: ", d:ACS_NamedExecuteWithResult("DList_Length", DBoard_AllSquaresTID));
+    Log(s:"");
+    
+    SetActivator(linkTID);
+    
+    while (true)
+    {
+        ACS_NamedExecuteWithResult("DBoard_LinkDebugInfo");
+        if (!DList_Iterate(true)) { break; }
+    }
+    
+    Log(s:"... done");
+}
+
+
+script "DBoard_LinkDebugInfo" (void)
+{
+    Log(s:"Link TID: ", d:ActivatorTID());
+    SetActivator(0, LINK_ACTOR);
+    Log(s:" - Actor TID: ", d:ActivatorTID(), s:", pos: <", f:GetActorX(0), s:", ", f:GetActorY(0), s:", ", f:GetActorZ(0), s:">");
+    Log(s:"");
+}

+ 7 - 0
pk3/acs/board_defs.h

@@ -0,0 +1,7 @@
+// Copyright © 2019 ijon <segfaultsamurai@gmail.com>
+// This work is free. You can redistribute it and/or modify it under the
+// terms of the Do What The Fuck You Want To Public License, Version 2,
+// as published by Sam Hocevar. See the LICENSE.txt file for more details.
+
+// Stores the TID of the first link of the list containing all boards squares.
+int DBoard_AllSquaresTID = -1;

+ 15 - 0
pk3/acs/lmaodice.c

@@ -0,0 +1,15 @@
+// Copyright © 2019 ijon <segfaultsamurai@gmail.com>
+// This work is free. You can redistribute it and/or modify it under the
+// terms of the Do What The Fuck You Want To Public License, Version 2,
+// as published by Sam Hocevar. See the LICENSE.txt file for more details.
+
+#library "lmaodice"
+
+#include "zcommon.acs"
+
+#include "util_defs.h"
+#include "util_funcs.h"
+#include "util_list.h"
+
+#include "board_defs.h"
+#include "board_build.h"

BIN
pk3/acs/lmaodice.o


+ 6 - 0
pk3/acs/util_defs.h

@@ -0,0 +1,6 @@
+// Copyright © 2019 ijon <segfaultsamurai@gmail.com>
+// This work is free. You can redistribute it and/or modify it under the
+// terms of the Do What The Fuck You Want To Public License, Version 2,
+// as published by Sam Hocevar. See the LICENSE.txt file for more details.
+
+#define PLAYERMAX 64

+ 31 - 0
pk3/acs/util_funcs.h

@@ -0,0 +1,31 @@
+// Copyright © 2019 ijon <segfaultsamurai@gmail.com>
+// This work is free. You can redistribute it and/or modify it under the
+// terms of the Do What The Fuck You Want To Public License, Version 2,
+// as published by Sam Hocevar. See the LICENSE.txt file for more details.
+
+function int cond(int c, int t, int f) { if (c) { return t; } return f; }
+
+function int min(int a, int b) { if (a < b) { return a; } return b; }
+function int max(int a, int b) { if (a > b) { return a; } return b; }
+
+function int middle(int a, int b, int c)
+{
+    if (a < b && a < c) { return min(b, c); }
+    return min(a, max(b, c));
+}
+
+function int itof(int a) { return a << 16; } // int to fixed
+function int ftoi(int a) { return a >> 16; } // fixed to int
+
+// multiply integer by fraction, and avoid overflows
+function int fractionMult(int num, int mult, int div)
+{
+    return ((num / div) * mult) + (((num % div) * mult) / div);
+}
+
+// convert to fixed point and divide, while avoiding overflows
+//  - specialized version of fractionMult above
+function int itofDiv(int x, int div)
+{
+    return ((x / div) << 16) + ((x % div) << 16) / div;
+}

+ 335 - 0
pk3/acs/util_list.h

@@ -0,0 +1,335 @@
+// Copyright © 2019 ijon <segfaultsamurai@gmail.com>
+// This work is free. You can redistribute it and/or modify it under the
+// terms of the Do What The Fuck You Want To Public License, Version 2,
+// as published by Sam Hocevar. See the LICENSE.txt file for more details.
+
+// Reminder:
+//  - AAPTR_TARGET points to the linked actor
+//  - AAPTR_MASTER points to the next link
+//  - AAPTR_TRACER points to the previous link
+
+#define LINK_ACTOR  AAPTR_TARGET
+#define LINK_NEXT   AAPTR_MASTER
+#define LINK_PREV   AAPTR_TRACER
+
+
+// Advances the script to the next item in the current list if there is one.
+//  Otherwise, stay at the current link. If backwards is true, 
+//  advance to the previous link instead.
+//
+// Possible return values:
+//   true: Advanced to the next/previous link.
+//   false: Currently at last/first link.
+
+function int DList_Iterate(int backwards)
+{
+    int oldTID = ActivatorTID();
+    int newTID = UniqueTID();
+    Thing_ChangeTID(0, newTID);
+    
+    if (SetActivator(0, cond(backwards, LINK_PREV, LINK_NEXT)))
+    {
+        Thing_ChangeTID(newTID, oldTID);
+        return true;
+    }
+    
+    SetActivator(newTID);
+    Thing_ChangeTID(0, oldTID);
+    return false;
+}
+
+
+// Creates a link set to a specific actor. If prevTID is nonzero, sets itself up
+//  as prevTID's next link. If nextTID is nonzero, sets itself up as nextTID's 
+//  previous link. If both are zero, the link remains unlinked.
+//
+// And if both prevTID and nextTID are nonzero, it only makes the link if prevTID
+//  is nextTID's previous link, and nextTID is prevTID's next link.
+//
+// In any case, links are transferred appropriately so that the list remains
+//  valid and doesn't lose any members.
+//
+// actorTID can be 0, and refers to the activator in that case.
+//
+// Possible return values:
+//   Any number above 0: The TID of the new link.
+//   -1: actorTID was nonzero and unused.
+//   -2: Either prevTID or nextTID were nonzero and unused.
+//   -3: Both prevTID and nextTID were specified, but they weren't linked to each other.
+
+script "DList_MakeLink" (int actorTID, int prevTID, int nextTID)
+{
+    if (actorTID != 0 && !IsTIDUsed(actorTID))
+    {
+        SetResultValue(-1);
+        terminate;
+    }
+    
+    if ((prevTID != 0 && !IsTIDUsed(prevTID)) || (nextTID != 0 && !IsTIDUsed(nextTID)))
+    {
+        SetResultValue(-2);
+        terminate;
+    }
+    
+    if (prevTID != 0 && nextTID != 0)
+    {
+        if (!ACS_NamedExecuteWithResult("DList_CheckLinked", prevTID, nextTID))
+        {
+            SetResultValue(-3);
+            terminate;
+        }
+    }
+    
+    int actorTID_old;
+    int actorTID_new = UniqueTID();
+    int linkTID = UniqueTID();
+    
+    if (actorTID != 0)
+    {
+        SetActivator(actorTID);
+        actorTID_old = actorTID;
+    }
+    else
+    {
+        actorTID_old = ActivatorTID();
+    }
+    
+    Thing_ChangeTID(0, actorTID_new);
+    
+    SpawnForced("ActorListLink", 0,0,0, linkTID);
+    
+    SetActivator(linkTID);
+    SetPointer(LINK_ACTOR, actorTID_new);
+    
+    int nextTID_old = nextTID;
+    int prevTID_old = prevTID;
+    int nextTID_changed = false;
+    int prevTID_changed = false;
+    
+    if (prevTID != 0 || nextTID != 0)
+    {
+        if (nextTID == 0)
+        {
+            if (SetActivator(prevTID, LINK_NEXT))
+            {
+                nextTID_changed = true;
+                nextTID_old     = ActivatorTID();
+                nextTID         = UniqueTID();
+                
+                Thing_ChangeTID(0, nextTID);
+            }
+        }
+        else if (prevTID == 0)
+        {
+            if (SetActivator(nextTID, LINK_PREV))
+            {
+                prevTID_changed = true;
+                prevTID_old     = ActivatorTID();
+                prevTID         = UniqueTID();
+                
+                Thing_ChangeTID(0, prevTID);
+            }
+        }
+        
+        SetActivator(linkTID);
+        SetPointer(LINK_PREV, prevTID);
+        SetPointer(LINK_NEXT, nextTID);
+        
+        if (prevTID != 0)
+        {
+            SetActivator(prevTID);
+            SetPointer(LINK_NEXT, linkTID);
+        }
+        
+        if (nextTID != 0)
+        {
+            SetActivator(nextTID);
+            SetPointer(LINK_PREV, linkTID);
+        }
+        
+        if (prevTID_changed) { Thing_ChangeTID(prevTID, prevTID_old); }
+        if (nextTID_changed) { Thing_ChangeTID(nextTID, nextTID_old); }
+    }
+    
+    Thing_ChangeTID(actorTID_new, actorTID_old);
+    SetResultValue(linkTID);
+}
+
+
+// Checks to see if the two given TIDs are linked. If eitherway is true, order doesn't
+//  matter; otherwise, leftTID must be the first link, and rightTID must be the second
+//  link.
+//
+// One of leftTID or rightTID can be 0 to refer to the activator, but if both are 0,
+//  the function returns false.
+//
+// This is a function purely because *holy fuck look at all that TID bullshit*
+//
+// Possible return values:
+//   1 (true): They are linked.
+//   0 (false): Anything else.
+
+script "DList_CheckLinked" (int leftTID, int rightTID, int eitherway)
+{
+    if (leftTID == 0 && rightTID == 0)
+    {
+        SetResultValue(false);
+        terminate;
+    }
+        
+    if (!(IsTIDUsed(leftTID) && IsTIDUsed(rightTID)))
+    {
+        SetResultValue(false);
+        terminate;
+    }
+    
+    int leftTID_old, rightTID_old;
+    int leftTID_new  = UniqueTID();
+    int rightTID_new = UniqueTID();
+    
+    // Handle 0 TIDs first
+    if (leftTID == 0)
+    {
+        leftTID_old = ActivatorTID();
+        Thing_ChangeTID(0, leftTID_new);
+    }
+    else if (rightTID == 0)
+    {
+        rightTID_old = ActivatorTID();
+        Thing_ChangeTID(0, rightTID_new);
+    }
+    
+    if (leftTID != 0)
+    {
+        SetActivator(leftTID);
+        leftTID_old = leftTID;
+        Thing_ChangeTID(0, leftTID_new);
+    }
+    
+    if (rightTID != 0)
+    {
+        SetActivator(rightTID);
+        rightTID_old = rightTID;
+        Thing_ChangeTID(0, rightTID_new);
+    }
+    
+    int ret = true;
+    
+    SetActivator(leftTID_new, AAPTR_MASTER);
+    ret &= (ActivatorTID() == rightTID_new);
+    
+    SetActivator(rightTID_new, AAPTR_TRACER);
+    ret &= (ActivatorTID() == leftTID_new);
+    
+    if (!ret && eitherway)
+    {
+        ret = true;
+    
+        SetActivator(leftTID_new, AAPTR_TRACER);
+        ret &= (ActivatorTID() == rightTID_new);
+        
+        SetActivator(rightTID_new, AAPTR_MASTER);
+        ret &= (ActivatorTID() == leftTID_new);
+    }
+    
+    SetResultValue(ret);
+    Thing_ChangeTID(leftTID_new,  leftTID_old);
+    Thing_ChangeTID(rightTID_new, rightTID_old);
+}
+
+
+// Gets the length of a linked list from anywhere along it. If listTID is 0, gets
+//  the length of the list the activator's a part of.
+//
+// Possible return values:
+//   Any value above 0: List length.
+//   -1: List doesn't exist.
+
+script "DList_Length" (int listTID)
+{
+    int ret = 1;
+    
+    if (listTID)
+    {
+        if (!SetActivator(listTID))
+        {
+            SetResultValue(-1);
+            terminate;
+        }
+    }
+    
+    int oldTID = ActivatorTID();
+    int newTID = UniqueTID();
+    Thing_ChangeTID(0, newTID);
+    
+    while (DList_Iterate(false)) { ret++; }
+    
+    SetActivator(newTID);
+    while (DList_Iterate(true))  { ret++; }
+    
+    Thing_ChangeTID(newTID, oldTID);
+    SetResultValue(ret);
+}
+
+
+// Adds an actor to the end of a linked list.
+// addTID can be 0, in which case it adds the current activator to the list.
+//
+// Possible return values:
+//  Any value above 0: TID of the new link.
+//  -1: Item was already in list, and duplicate entries aren't allowed.
+//  -2: List doesn't exist.
+//  -3: The link wasn't created properly for some reason.
+
+script "DList_Append" (int listTID, int addTID, int allowdupe)
+{
+    if (listTID == -1 || !IsTIDUsed(listTID))
+    {
+        SetResultValue(-2);
+        terminate;
+    }
+    
+    if (addTID != 0) { SetActivator(addTID); }
+    
+    int addTID_old = ActivatorTID();
+    int addTID_new = UniqueTID();
+    Thing_ChangeTID(0, addTID_new);
+    
+    SetActivator(listTID);
+    
+    int linkTID = UniqueTID();
+    int linkTID_old;
+    
+    while (true)
+    {
+        linkTID_old = ActivatorTID();
+        Thing_ChangeTID(0, linkTID);
+        
+        SetActivator(linkTID, LINK_ACTOR);
+        
+        if (ActivatorTID() == addTID_new && !allowdupe)
+        {
+            Thing_ChangeTID(linkTID, linkTID_old);
+            Thing_ChangeTID(addTID_new, addTID_old);
+            SetResultValue(-1);
+            terminate;
+        }
+        
+        if (!SetActivator(linkTID, LINK_NEXT)) { break; }
+        Thing_ChangeTID(linkTID, linkTID_old);
+    }
+    
+    // Reached end of list, activator is last link
+    int newLinkTID = ACS_NamedExecuteWithResult("DList_MakeLink", addTID_new, linkTID);
+    Thing_ChangeTID(linkTID,    linkTID_old);
+    Thing_ChangeTID(addTID_new, addTID_old);
+    
+    if (newLinkTID <= 0)
+    {
+        Log(s:"\cg[ERROR]\c- DList_Append failed to append (DList_MakeLink return code: ", d:newLinkTID, s:")");
+        SetResultValue(-3);
+        terminate;
+    }
+    
+    SetResultValue(newLinkTID);
+}

+ 35 - 0
pk3/decorate/boardSquares.txt

@@ -0,0 +1,35 @@
+actor ActorListLink
+{
+    // Target actor pointer: linked actor
+    // Master actor pointer: next link
+    // Tracer actor pointer: previous link
+    
+    // For the board: stores whether the linked actor leads to this square (true)
+    //  or if this square leads to the linked actor (false)
+    var int user_board_isorigin;
+    
+    +NOINTERACTION
+    +SERVERSIDEONLY
+    
+    States
+    {
+      Spawn:
+        TNT1 A -1
+        stop
+    }
+}
+
+actor BasicBoardSquare
+{
+    +NOINTERACTION
+    +SERVERSIDEONLY
+    
+    States
+    {
+      Spawn:
+        TNT1 A  0
+        TNT1 A  0 ACS_NamedExecuteWithResult("DBoard_InitSquare")
+        TNT1 A -1
+        stop
+    }
+}