Bay 12 Games Forum

Please login or register.

Login with username, password and session length
Advanced search  
Pages: 1 ... 669 670 [671] 672 673 ... 795

Author Topic: if self.isCoder(): post() #Programming Thread  (Read 818121 times)

DragonDePlatino

  • Bay Watcher
  • [HABIT:COLLECT_WEALTH]
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #10050 on: September 17, 2016, 11:40:22 am »

Ah, yes. I forgot to mention, I'm not using my own JSON library. I'm using nlohmann's JSON for Modern C++. It's a really intuitive library that packs JSON data into custom STL containers that you can iterate through and export to files. Only problem is, if you want to have a data-driven game and parse objects from JSON data, you have to feed the data line-by-line into the object's constructor like this:

Code: [Select]
Entity( entitydata[type]["pos"]["face"],
entitydata[type]["pos"]["hitbox"]["x"],
entitydata[type]["pos"]["hitbox"]["y"],
entitydata[type]["pos"]["hitbox"]["w"],
entitydata[type]["pos"]["hitbox"]["h"],
entitydata[type]["pos"]["subpos"]["x"],
entitydata[type]["pos"]["subpos"]["y"],
entitydata[type]["pos"]["vel"]["x"],
entitydata[type]["pos"]["vel"]["y"]));
      
Which really, is pretty verbose and less-than-ideal. But I can't think of a better way of parsing JSON data directly into game objects.

LoSboccacc

  • Bay Watcher
  • Σὺν Ἀθηνᾷ καὶ χεῖρα κίνει
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #10051 on: September 17, 2016, 12:28:18 pm »

if it can be read from streams, it's going to be better to have the data in a nice formatted string, then convert that in a stream and feed it to the parser
Logged

Spehss _

  • Bay Watcher
  • full of stars
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #10052 on: September 24, 2016, 05:19:43 pm »

So I'm learning about abstract data types. Currently on lists, with a container class that holds some unit of data and a pointer to another container, the "next" in the list.

Wrote example code to practice the concept. Wrote a couple functions to help with navigating to specific items in the list. I can add things to the end of the list ok. Trying to write a function that removes a specific unit in the list and set the pointer from the previous unit in the list to 0 to avoid dangling pointers. Simplest case, the item to be removed is the one at the end, so I don't need to bother with keeping it all connected if removing a unit in the middle of the list.

Function removeFromList doesn't work and crashes the program. I can delete the Node object but can't change the pointer of the previous Node in the list, presumably this is what crashes the program in removeFromList. Pretty sure it's due to passing by value instead of passing by reference in the getNode() function. Initially the addToList function passed pointers by value, not reference, and this worked, but after finding an issue with passing nullptrs as an argument and adding code to initialize the first item in the list in this case, it became necessary to pass the pointer by reference, otherwise the change was lost as soon as the function ended and went out of scope.

Basically I'm not sure what's wrong with removeFromList() and I've been looking at it for so long that I'm losing any sense of what I'm doing. Help?

Spoiler: c++ code (click to show/hide)
Logged
Steam ID: Spehss Cat
Turns out you can seriously not notice how deep into this shit you went until you get out.

RulerOfNothing

  • Bay Watcher
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #10053 on: September 24, 2016, 07:49:41 pm »

The problem is that your removeFromList function doesn't behave sensibly if index is equal to 0 since it will try to get the node with the index of -1 to put in prevNode. You'll need to have special code for handling the case where index is 0 unless you want to redesign your linked list container.

Also I had a look at the addToList function and you're letting the new nodes become inaccessible. You want something like:
Code: [Select]
template <class Thing>
void addToList(Node<Thing>* &head, Thing data)
{
if(head==nullptr)
head=new Node<Thing>(data);
else
{
Node<Thing>* endOfList=getNode(head);
head=new Node<Thing>(data, endOfList);
}
}
so that the new node actually becomes part of the data structure.
« Last Edit: September 24, 2016, 07:53:32 pm by RulerOfNothing »
Logged

Reelya

  • Bay Watcher
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #10054 on: September 24, 2016, 08:53:46 pm »

The additional dummy node for the head is actually preferable in many cases: it costs one extra node, but you save space on reduced code complexity, and it speeds things up by not having to do that extra check for a null head every time you access the list.

If the list can have a null head pointer, you have to check for it being empty every time you call any of the methods which do things with the list. But "null head" is an extremely rare condition on a list of any size that you're working on for the lifetime of the program session.

Also, RulerOfNothing, if-statements should have the most-likely branch first. The compiler uses that to determine which path to do branch-prediction on. If the if statement is false, then the CPU's instruction pipeline gets flushed. So this would be faster:

Code: [Select]
template <class Thing>
void addToList(Node<Thing>* &head, Thing data)
{
if(head!=nullptr)
{
Node<Thing>* endOfList=getNode(head);
head=new Node<Thing>(data, endOfList);
}
else
head=new Node<Thing>(data);
}
« Last Edit: September 24, 2016, 09:01:05 pm by Reelya »
Logged

Spehss _

  • Bay Watcher
  • full of stars
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #10055 on: September 24, 2016, 08:59:56 pm »

The problem is that your removeFromList function doesn't behave sensibly if index is equal to 0 since it will try to get the node with the index of -1 to put in prevNode. You'll need to have special code for handling the case where index is 0 unless you want to redesign your linked list container.

Ooooooooooh. It didn't even occur to me that by passing 0 as a default parameter in removeFromList() then the function could wind up trying to pass -1 into getNode(). getNode(0) would return the pointer of the last node in the list with an argument of 0, but getNode(-1) would break everything by either running infinitely or returning nullptr, which would then try to be dereferenced in a method call and crash the program. Thanks for pointing that out.

Also I had a look at the addToList function and you're letting the new nodes become inaccessible. You want something like:
Code: [Select]
template <class Thing>
void addToList(Node<Thing>* &head, Thing data)
{
if(head==nullptr)
head=new Node<Thing>(data);
else
{
Node<Thing>* endOfList=getNode(head);
head=new Node<Thing>(data, endOfList);
}
}
so that the new node actually becomes part of the data structure.

Head is supposed to point to the first node in the list though. Accessing anything in the list depends on head pointing to the first node in the list. Setting head to point to the new node at the end of the list would cause all the previous nodes' addresses to be lost. AddToList() as far as I can see works fine as it is. The new node when calling the constructor takes the temporary pointer addr, which points to the previous node in the list, and sets that node to point to the new node calling the constructor.

Only reason I brought addToList() up was that I thought it was (somehow) relevant to the issue causing my program to not work.

The additional dummy node for the head is actually preferable in many cases: it costs one extra node, but you save space on reduced code complexity, and it speeds things up by not having to do that extra check for a null head every time you access the list.
Would that single if statement check every time the addToList or removeFromList functions are called really make that much difference in speed? It's not a loop or an extensive recursive function or anything.
Logged
Steam ID: Spehss Cat
Turns out you can seriously not notice how deep into this shit you went until you get out.

Reelya

  • Bay Watcher
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #10056 on: September 24, 2016, 09:03:28 pm »

Well it depends. Extra instructions gum up the icache, so even a single extra instruction could slow things down a lot if it caused a paging issue in the icache. It's a "planets aligning" type issue, so it's not predictable from just looking at one bit of code. Basically, a small amount of extra memory (in this case a single dummy list node) streamlines the code a lot since you never have to check for the rare "null head" condition. Things are therefore going to scale up a lot better, for example if your complier inlines the list functions, then you get that if statement replicated any time you use the list, meaning it actually took up more space. Also, less if statements means more readable compact code.

Also, the null-check as written assumes that null is the default choice, so therefore the CPU would constantly flush the instruction pipeline whenever that code is run (since the head is almost never null, but we're assuming it always is). The compiler can't reason about what your code is intended to do, or how it's going to be used in a real-world situation. So it just guesses that the first path of the if is the one to preload the instructions for. So if's that would tend to be false are something that you can optimize away by inverting them: optimize for the "true" case.

So the bigger issue with if statements is not how many CPU cycles they take: it's that they cause the pipeline to be flushed if they go onto the "else" branch (which includes if statements without an explicit "else", because it's implied).
« Last Edit: September 24, 2016, 09:21:16 pm by Reelya »
Logged

RulerOfNothing

  • Bay Watcher
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #10057 on: September 24, 2016, 09:17:38 pm »

Right, the way your linked list is implemented is a bit confusing but I noticed something wrong with the getNode function:
Code: [Select]
template <class Thing>
Node<Thing>* getNode(Node<Thing>* head, int index=0)
{
Node<Thing>* addr=head;
int pos=1;
while(addr!=nullptr&&pos!=index)
{
if(pos==index)
return addr;
else if(addr->getNext()==nullptr&&index==0)
return addr;
else if(addr->getNext()!=nullptr)
{addr=addr->getNext(); ++pos;}
}
return nullptr;
}
The problem here is if you call it with a non-zero index (that is a valid index into the list) then when pos becomes equal to index then the while loop will stop (since pos!=index is no longer true) and the function will return nullptr rather than the node being pointed to by addr. You should remove the '&&pos!=index' since this is already handled by the if statement.
Logged

Reelya

  • Bay Watcher
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #10058 on: September 24, 2016, 09:28:59 pm »

You need to get rid of the last else-if
Code: [Select]
else if(addr->getNext()!=nullptr)
{addr=addr->getNext(); ++pos;}
^ because this will stop updating addr, once addr->getNext() is null, therefore addr will never be null, and pos will never be updated either. Just get rid of the "if" part
Code: [Select]
else {addr=addr->getNext(); ++pos;}Now, addr will be set to null when addr->getNext() becomes null, and the while loop will end. The updated code with RulerOfNothing's simplification etc is:

Spoiler (click to show/hide)
The rest of my suggested fixes would include reordering the if statements so that it's not doing tons of unnecessary calculations then throwing them out when a rare condition isn't met. For example, this line:

Quote
else if(addr->getNext()==nullptr&&index==0)
is doing a complex calculation first, every time, then checking whether it's even relevant (index==0). Putting "index==0" first would speed this up for cases where index wasn't zero, since it would skip the expensive function call.

Also, it's checking "if pos==index" every time through the loop, without excluding this check in the times when index==0 is true (so pos==index can never be true at the same time index==0, so there's no need to check both in the same iteration). By reordering things to skip the pos==index check when index==0 then you can save clock cycles in the index==0 cases. e.g.

Spoiler (click to show/hide)

Well that's got index==0 case down to two if-checks per loop, one always true, one usually false. That still means the instruction pipeline will be flushed every single iteration (except for the final one, but that is followed by a stack return, so it's not going to help). We can improve that by assuming we didn't find the end of the list, as the default if-branch

Spoiler (click to show/hide)

So, "index==0" now only hits "true" if statements for all checks until the final one. "Index != 0" still flushes the pipeline every loop due to assuming index==0 is the default. To speed things up any further, the index==0 case should be split off into a separate "getTailNode" function. Also note, that you're creating a "head" variable then only using it once. You don't need to make a separate addr pointer at all, you already have one (because it's a copy of the passed pointer). just pass it as addr.

Spoiler (click to show/hide)

EDIT: one final thing that would simplify the getNode function is to do away with "pos" completely, and decrement index each time through the loop. Then you could get it so that you're comparing index to a constant (0) rather than another variable. Which is faster because there's an actual CPU instruction code that branches if something = zero. The trick here is comparing things in a relative sense instead of an absolute sense, so you can compare things to constants, especially zero, which is treated as a special case by the compiler and CPU.

Spoiler (click to show/hide)
« Last Edit: September 25, 2016, 04:08:37 am by Reelya »
Logged

itisnotlogical

  • Bay Watcher
  • might be dat boi
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #10059 on: September 25, 2016, 08:02:24 pm »

In the Unity game I'm creating, C# is the primary language but I'm using an add-on that can interpret Javascript at runtime to create enemy behavior and spell effects. Since I don't intend to support modding and a very similar thing can be done in Unity with ScriptableObjects, I'm wondering if this wasn't just a mental thing to make myself feel better about doing the exact same amount of work.

Well, I suppose I don't have to create a whole new class inheriting from some PowerBase class every time I want to create a new ability, so that's one bit of extra convenience.
« Last Edit: September 25, 2016, 08:08:55 pm by itisnotlogical »
Logged
This game is Curtain Fire Shooting Game.
Girls do their best now and are preparing. Please watch warmly until it is ready.

TheBiggerFish

  • Bay Watcher
  • Somewhere around here.
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #10060 on: September 29, 2016, 02:54:18 pm »

In other news, apparently Aptana Studio 3.6.1 is suffering from installer buggery where you need to install things before you install things.  This is not fun.
Logged
Sigtext

It has been determined that Trump is an average unladen swallow travelling northbound at his maximum sustainable speed of -3 Obama-cubits per second in the middle of a class 3 hurricane.

Dutrius

  • Bay Watcher
  • No longer extremely unavailable!
    • View Profile
    • Arcanus Technica
Re: if self.isCoder(): post() #Programming Thread
« Reply #10061 on: September 29, 2016, 04:44:03 pm »

Learning Python for my Networking module. Trying to remember how to do regular expressions when you last did it two years ago, and then only briefly.
Logged
No longer extremely unavailable!
Sig text
ArcTech: Incursus. On hold indefinitely.

TheBiggerFish

  • Bay Watcher
  • Somewhere around here.
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #10062 on: September 29, 2016, 04:48:12 pm »

Learning Python for my Networking module. Trying to remember how to do regular expressions when you last did it two years ago, and then only briefly.
Ouch.
Logged
Sigtext

It has been determined that Trump is an average unladen swallow travelling northbound at his maximum sustainable speed of -3 Obama-cubits per second in the middle of a class 3 hurricane.

Levi

  • Bay Watcher
  • Is a fish.
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #10063 on: September 29, 2016, 04:51:23 pm »

Learning Python for my Networking module. Trying to remember how to do regular expressions when you last did it two years ago, and then only briefly.

Rubular is my favorite handy site for that.  Made for Ruby, but I don't think Python regular expressions are any different.

http://rubular.com/

Edit:  Oh, I just found this as well:  http://pythex.org/
Logged
Avid Gamer | Goldfish Enthusiast | Canadian | Professional Layabout

Dutrius

  • Bay Watcher
  • No longer extremely unavailable!
    • View Profile
    • Arcanus Technica
Re: if self.isCoder(): post() #Programming Thread
« Reply #10064 on: September 29, 2016, 04:55:54 pm »

Regex seems to be pretty much the same regardless of language. At least the documentation of Python's re module has pretty decent documentation.
Logged
No longer extremely unavailable!
Sig text
ArcTech: Incursus. On hold indefinitely.
Pages: 1 ... 669 670 [671] 672 673 ... 795