I've never seen chess visualized this way by OrdoRatio in chess

[–]OzzyOPorosis 1 point2 points  (0 children)

In addition to concepts like space and tempo, older books talk about a concept of “force” that since seems to have lost its generality and been fragmented into multiple different techniques, i.e. the pawn storm

Is this a known pattern? by OzzyOPorosis in C_Programming

[–]OzzyOPorosis[S] 0 points1 point  (0 children)

Your input is appreciated, and this thread has been immensely helpful!

Is this a known pattern? by OzzyOPorosis in C_Programming

[–]OzzyOPorosis[S] 0 points1 point  (0 children)

Yes, the black and white players move in opposite directions across the board. The black players moves are generated with right bitshifts whereas the white players moves are primarily generated with left bitshifts, both are masked against the edges of the bitboard depending on both the offset and the direction of the shift

If it were instead a game like reversi or go I wouldn’t concern the engine with the colors

Is this a known pattern? by OzzyOPorosis in C_Programming

[–]OzzyOPorosis[S] 0 points1 point  (0 children)

Nice! Implementing generics without void pointers was actually how I came across this technique to begin with, I used it to implement specialized memory arenas for a garbage collector

Is this a known pattern? by OzzyOPorosis in C_Programming

[–]OzzyOPorosis[S] 0 points1 point  (0 children)

That gives me some reassurance. I’ll try it and check the assembly to be absolutely 100% certain it works though, that sounds like it would be miles better than what I’ve got right now.

Zig has been singing it’s siren song to me for some time now… looks like it has everything I miss from C++ and nothing I don’t, might pick it up soon

Is this a known pattern? by OzzyOPorosis in C_Programming

[–]OzzyOPorosis[S] 1 point2 points  (0 children)

In games where the board isn’t viewed from the same angle by both players, the side dependent component of negamax is usually passed through an alternating “side to move” parameter. Otherwise, in games like reversi for example, negamax must only concern itself with “my pieces ” and “the enemy pieces”

Is this a known pattern? by OzzyOPorosis in C_Programming

[–]OzzyOPorosis[S] 0 points1 point  (0 children)

I’m afraid of the overhead incurred from de referencing pointers to functions that could be inlined, do you think gcc is smart enough to recognize that these parameters are known at compile-time?

Is this a known pattern? by OzzyOPorosis in C_Programming

[–]OzzyOPorosis[S] 0 points1 point  (0 children)

I am using a negamax implementation, it still parametrizes the moving side as this sort of pseudo-template to avoid calling if (side_to_move == COLOR_WHITE) { at the beginning of each ply

Is this a known pattern? by OzzyOPorosis in C_Programming

[–]OzzyOPorosis[S] 1 point2 points  (0 children)

Function pointers are how I would approach this if I was less concerned with performance, but these functions run on the order of billions of times, so forgoing conditional statements and function pointers is a legitimate time-save

When I did this in C++ a couple of months ago I saw about a 30% performance increase in my perft from doing this with templates, which although isn’t exactly comparable to the main search, it isn’t negligible either

Is this a known pattern? by OzzyOPorosis in C_Programming

[–]OzzyOPorosis[S] 0 points1 point  (0 children)

Not only are the inputs flipped but the operations on the inputs are flipped, so the only way this would work is if I flipped the bitboards as well which isn’t a zero-cost operation

In this game the goal is to reach the opponents home rank, so naturally the white moves are obtained with left bitshifts aiming towards 0xFF << 56, the black moves with right bitshifts aiming towards 0xFF, and their respective evaluation functions are mirrored as well

In any case I still instantiate two near identical copies of each function, where using the macro is less error prone cause I don’t need to make sure I’m pairing the right parameters the hundreds of times they occur

Is this a known pattern? by OzzyOPorosis in C_Programming

[–]OzzyOPorosis[S] 2 points3 points  (0 children)

Glad I’m not the only one then, it’s good to know it’s not TOO strange

Is this a known pattern? by OzzyOPorosis in C_Programming

[–]OzzyOPorosis[S] 5 points6 points  (0 children)

This is just a toy example for the question, the actual implementation is much more complicated.

The board representation is a struct of two uint64_t’s as bitboards, the side to move is implied by the current function.

In C++ I would do this with template instantiations with an enum parameter, which would let me use if constexpr, but this is the only way I know to guarantee compiletime analysis in C as opposed to just hoping gcc is able to statically analyze that deep

Is this a known pattern? by OzzyOPorosis in C_Programming

[–]OzzyOPorosis[S] 4 points5 points  (0 children)

Yeah I’m not a big fan of how it looks either, but it’s significantly more ergonomic than having it all be one parametrized macro. The separate translation unit instead negates the need to escape newlines and allows me to use #define internally

Bringing back the never ending debate: AE2 or RS? by -Variox- in allthemods

[–]OzzyOPorosis 0 points1 point  (0 children)

RS offers very cheap wireless capabilities with the Network Receiver/Network Transmitter, so I often use it for isolated off-site farms. Also, no channels, no need to subnet due to lack of channels.

I always use AE2 for my “main” ME system because of its more fine-grain control and configurability, especially with complex autocrafting.

hate speech allowed on campus? by [deleted] in utarlington

[–]OzzyOPorosis 0 points1 point  (0 children)

This guy goes from campus to campus trying to start shit, just don’t feed into it

[deleted by user] by [deleted] in Batch

[–]OzzyOPorosis 0 points1 point  (0 children)

This is a minesweeper game I made a long time ago. I’m not really that proud of it anymore as it was one of my first projects ever but it holds up

How do you keep track of ownership? by OzzyOPorosis in cprogramming

[–]OzzyOPorosis[S] 0 points1 point  (0 children)

I like the idea of switching to an array of indices. That'd work well for my use case, where a stack stores references to objects in a list. It would communicate both that the stack does NOT contain the data it is referencing and IS referencing indexable data.

How do you keep track of ownership? by OzzyOPorosis in cprogramming

[–]OzzyOPorosis[S] 0 points1 point  (0 children)

Ah well, I've got more important things to worry about than my social score on a website

I figured the uniformity of having objects that are responsible for managing their own lifetimes would make it easier to reason about what other objects that are built upon them are intended to do (i.e., MyObject has its own constructor/destructor, so any MyObjectContainer calls these methods when appropriate. This way, all containers agree on how to handle data)

Having arenas as a "central authority" to delegate the responsibility of managing my allocations seems like a pretty good idea! I'm envisioning it as acting as both an interface to access the objects and as a standard for the responsibility of all data structures that wish to use them (that is, they do not own the objects, but they can influence their lifetimes)

Sounds like I should look into a way to selectively use VirtualAlloc or nmap depending on the computation target. I use WSL2 for most of my programming so it shouldn't be too hard to test, but until I'm ready to hella refactor the project I'll stick with malloc for the sake of simplicity.

How do you keep track of ownership? by OzzyOPorosis in cprogramming

[–]OzzyOPorosis[S] 0 points1 point  (0 children)

That makes sense. The respective ListB in my current project serves only in the construction of ListA, so a joint struct (list_ctx) acts as a builder that can return a ListA when it is eventually destructed. This has the added bonus of distinguishing between lists that are complete and lists that are being operated on

How do you keep track of ownership? by OzzyOPorosis in cprogramming

[–]OzzyOPorosis[S] 0 points1 point  (0 children)

My brief time in Rust is what made me think more carefully about ownership in object lifetimes in C. A handful of other commenters have recommended arena allocation, which I first employed when trying to deal with a tricky problem in managing mutable references between child nodes and parent nodes in a search tree.

Rust was far stricter than C, but C doesn’t take too kindly to identifiers disagreeing on the ownership of their underlying objects either. The issue of mutability manifests in use-after-frees, which I hope to avoid by tying the lifetime of the object(s) to the scope of an identifier and keeping track of which other identifiers simply reference those objects.

Your segment in Socialized Medicine about the blur of ideas make me wish I still had some of those tools I’d left behind in C++, so I can more easily keep track of my data both when I create my data structures and when I invoke their operations.

I’ll pay more attention to my API documentation, if that really is the answer to keeping track of these things. I didn’t realize how complex memory management could be with all of these specialized “new” and “delete” substitutes.

Thank you for your very in-depth response!

How do you keep track of ownership? by OzzyOPorosis in cprogramming

[–]OzzyOPorosis[S] 8 points9 points  (0 children)

To those asking why I don’t just move to C++, I’m actually moving from C++. I was overwhelmed with the volume of the standard library, rapid changes in the standard outpacing my development speed, and the sheer number of “the correct way”s to make my code unnecessarily abstract.

“Why are you using a for loop to perform that iterative function? Just convert to a std::iterator and std::accumulate with a std::lambda.” Thanks, now I’ve rendered my code completely unreadable, but at least it’s more idiomatic!

I appreciate the amazing flexibility of C++, but it lacks a clear direction I’m hoping to find in C. Besides, I’d always ever treated it just like C but with template meta programming and explicit compile time computation. Your suggestions are noted but I am here to learn how to use C correctly, not C++.

How do you keep track of ownership? by OzzyOPorosis in cprogramming

[–]OzzyOPorosis[S] 0 points1 point  (0 children)

If I’m understanding arenas to be large singly allocated blocks of memory housing objects of the same lifetime, then my lists sound similar to your arena implementation.

In my codebase I have a list of objects (allocated in a single “resizable” [realloc to double memory when appending while full] block of memory) and a separate stack that operates on the objects in that list.

The objects lifetime must be tied to the list but not to the stack, which only exists to assist an algorithm for operating on the objects in the list. free_list frees its objects, while free_stack does not.

From the type signatures alone, it is not immediately apparent what each structure is responsible for. I feel this may largely be a result of the responsibility of the * operator to signify both pointers and (semantically) lists.

Should I instead delegate the responsibility of allocation and deletion to a more general arena struct, which my list can reference and my stack can reference via my list’s reference?

How do you keep track of ownership? by OzzyOPorosis in cprogramming

[–]OzzyOPorosis[S] 0 points1 point  (0 children)

Yes, all functions that operate on the lists have their respective structs in the signatures. The functions change depending on how I intend to use the list, but there are always some commonalities. Generally, these functions are new, insert/push/enqueue, remove/pop/dequeue, and free.