• Welcome to Valhalla Legends Archive.
 
Menu

Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Messages - FrOzeN

#1
StarCraft / Re: SC2 Beta Review!
March 15, 2010, 03:43 AM
Absolutely loving it.

From the start of a game it feels you must do a lot more in order to keep up. The 6 worker start really gets the game going a lot faster.

Protoss absolutely demolish ground armies with the right mix, but struggle a bit against air unless you know what you're doing. Zealot rushes with Protoss are pretty useless against any decent player, especially now that Zerg has Roaches. I've also found The Mothership to be extremely helpful with it's vortex against a bunch of anti-air units. The new chrono boost feature is great too, it's something everyone should be constantly using throughout a game.

Zerg's new unit Roaches are great for rushing. Most inexperienced players will get stomped on by them, which does feel a bit unbalanced at a low level. The Queen is now a must-have, and I usually have one at each base. Their larva spawn means no more multiply hatcheries everywhere, and they also provide you with the ability to spawn creep tumor which basically expands your creep. That ability combined with the Overlords new ability to drop creep allows you to control your creep, which Zerg units move over faster than on regular terrain. Mutalisks are much of the same as before, though, I find Protoss more vulnerable to them now. Unless Protoss has a few Phoenixes (which annihilate Muta's) you can usually do some nice damage around their base. Another new thing is the Nydus setup. It no longer needs creep to deploy, and has multiply exits. I find once I'm on my 3rd base I place an army of units within the Nydus and have an exit point in each base for quick defence. This also means you must ensure scouting around your base is done as all an enemy needs is vision and 20 seconds before the swarm arrives.

Terran almost always start of with a depot and barracks wall-in. Without it, surviving a rush is seems nearly impossible. And if you do survive the rush, then you'll be at a disadvantage with the resource/time loss to counter it. I've found with a few games, after you hold of the first wave with your wall, an immediate counter-attack using a few Marauders and a bunch of Marines really pushes them back. The new monster unit Thor doesn't really seem worth the cost. If you're versing any Protoss player by the time you have Thor(s), they'll have Immortals which chew through them. I'd rather just spend money on tanks with air support. Vikings are definitely my favourite Terran unit, their ability to be either air or ground is great fun. I find them commonly being used as a drop. Cloaked banshees are similar to wraiths, except with no air attack, they instead plow through units and buildings. Unfortunately I found that out the same time I found out that Overlords no longer detect. :(
#2
I've got beta now, I'm Blaziner.Blaziner.

I added MyndFyre, Sixen, and SNiFFeR. :)
#3
The AI seems really easy, maybe I haven't switched it to a harder AI yet.. :(

http://img13.imageshack.us/img13/9484/67476563.jpg
#4
Battle.net Bot Development / Re: Flooding Packets
September 04, 2008, 04:23 AM
IIRC, In StarCraft when clicking the join game button (which brings up the game list) and then hitting exit you'll get disconnected for flooding by repeating this too fast.
#5
Web Development / Re: SQL Databases
May 27, 2008, 08:22 AM
It really depends on the data you'll be storing. You have to determine how flexible your database needs to be. If you just wanted to know the user's main address, then putting it all into one table would probably be sufficient. But say the information you were collecting required room to allow for client's that have two or more addresses. In that scenario you would create a second table which stored all the address' and referenced each address to a ClientID.
#6
I've never used an ampersand infront of an array like that so I can't be too sure, but I have a feeling that &stdid[i] is being expanded to &*(stid+i) which is treating the value stored in the initial location as the address. I think changing &stdid[i] to stid+i should fix the problem (note this also applies to stsc).

Another thing I picked up with that code, you don't really seem to use the i and therefore could change your code to:
while (fgets(buffer, 2048, pfile) != NULL)
{
sscanf(buffer, "%d %d", stid, stsc);
printf("%d\t\t%d\n", stid++, stsc++);
}

Note that the ++ must come after the variable so it uses the original value of i in the printf() call before it increases it.

I may be wrong though and &array[index] might just do things correctly.

[EDIT] Also, for tabs use \t rather than putting tabs within strings. It makes it easier to distinguish when reading over code.
#7
Quote from: brew on April 01, 2008, 08:56 PM
Honestly, who would believe that to be a valid packet? It appears to consist of a dword of some random-ish value that's too low to be a tick count (195Ch), followed by a WORD (11h), the stringlist, and a few more binary values? If I recall correctly, it's a standard of blizzard's to put all numeric values before the strings. It would just make more sense that way. Not to mention how it's mixed binary-string-binary, and it makes use of 2 byte numeric values which have not been seen in recent battle.net packets. It's total bullshit.
You actually went as far as to analyze the fake packet he posted? The "Joining product-specifc channel diablo usa-1" message kind of gave it away.
#8
Testing Forum / Re: =
April 01, 2008, 07:57 PM
He just took the quote from Explicit's post from two years ago.
#9
Awesome April fools joke. You had me momentarily. :)
#10
Fun Forumâ„¢ / SC2 Unit - Tauren Marine
April 01, 2008, 06:13 AM
http://eu.starcraft2.com/features/terran/taurenmarine.xml

Neat April fools joke.

Hopefully they include these units in a secret cow level or something. That'd be awesome. :)
#11
.NET Platform / Re: Object Oriented Design Help
March 24, 2008, 10:54 AM
Quote from: MyndFyre[vL] on March 23, 2008, 11:44 PM
I disagree FrOzeN.  3-tier design doesn't really make sense in this domain; there is very little in terms of "business logic" that is needed for such an approach.

3-tier design conceptually looks like this:

Presentation
====
Business Rules
====
Data

One alternative could be Model-View-Controller.  This provides for interaction between the three tiers, but still cleanly addresses separation of concerns.
Whoops, sorry. I completely threw off my terminology. I haven't yet looked much into design patterns (will be doing soon), but what I was implying I think would of been the layered application approach. The 3-tier solution is more distinctly used when the layers are separated for means of scalability (among other reasons).

[EDIT] I had a quick look over the MVC which looks very nice. Just one thing that hit my curiosity, why has MSDN placed it under Web Presentation Patterns opposed to something more generic (being that you'd use this model outside of web-specific implementations)?
#12
.NET Platform / Re: Object Oriented Design Help
March 23, 2008, 07:34 PM
Quote from: NicoQwertyu on March 23, 2008, 02:14 PM
QuoteThis object will be the overall [core bot] class, and further bot objects with more features will derive off it.
Derive off it -- as in [core bot] will inherit the methods and properties of all other classes built around it? I doubt that's what you were trying to explain, but that's how I read it.  :-[
"Derive off it" means they'll inherit it, not have it inherit them.

So [core bot] would be a raw structure for a bot. You then may want to add a bunch of moderation features as methods/properties. You could create an [ops bot] class and inherit the [core bot] (so you say "Ops bot class derives from the Core bot class"). In this [ops bot] class you now only have to implement the new features you wanted to add, such as a method like SweepBan(channel).

Quote from: NicoQwertyu on March 23, 2008, 02:14 PM
QuoteAnyway, getting back on track. In VB.NET, setting something to 'Nothing' just changes what the reference to the object (being the variable) is treated as. It doesn't do any explicit memory freeing, nor does it even call the Dispose() method. When the object goes out of scope, it will be handled like any other dynamically allocated object through .NET's garbage collection.

Back in your code again, for that scenario, I don't think you'd need to implement IDisposable. As I said before, the idea of it is to provide a way of telling an object that it needs to clean up it's unmanaged resources. For example, connecting to a SQL Database to read/write a bunch of data, or opening a file to read/write a bunch of data, etc. Holding onto that connection, or keeping the file handle open until the garbage collection gets around will waste resources. It will also prevent that file being accessed until it's handle is closed. By implementing IDisposable in those cases creates an insurance that once you've finished working with them, they'll be freed up properly.
Is the massive List(of T) I have floating around in memory an unmanaged resource?
No, it's a managed object. An unmanaged object is something that's not controlled by the Common Language Runtime (CLR). Although the list may use up a bit of memory, using dispose doesn't create any magic for this case. The garbage collection is already well aware of this memory, and will free it when appropriate. As the memory isn't attached to something really important like a file handle, it doesn't require immediate dismissal.

Quote from: NicoQwertyu on March 23, 2008, 02:14 PMThe channellist can inherit databasecore, and add a few methods for manipulating the control on the form, and changing icons. The user objects in the channel can derive from Database.User, and just add a few more properties for ping and icon. So it's not a total failure.

Edit: Well, the above is almost true. It's kind of impossible to implement without overriding just about everything, however.  >:(
Essentially, if you want to design your application in a full OOP approach, then you'll want to follow the multi-tier architecture. This means you should separate your user interface, your logic, and your data. In the case of a bot, your data (data tier) would be the Config.ini, userlist.txt, and similar files which store the data. The logic (application tier) would be all the objects that process this data and manage a connection from Battle.net. And your user interface (presentation tier) is the display your user sees, such as the form and listview. This means that you don't want your channel list controlling your database. It should be completely separate, and the logic from the application tier will parse the information to events (or possibly setup delegated functions), and then the presentation tier will deal with displaying this data on the interface.

When a user does something like pressing enter in the chat box, that message should have 'basic' checking done at the KeyPress() level, and then parse it to the application tier (Bot.SendChatMessage(message)) where it will process and handle the rest. By separating these layers, your bot connection is able to be completely independent from the GUI, which may be an option you want to give a user. More importantly, if you want to reuse the bot object in another project, it doesn't have any dependencies tied to the interface of the first project it was created in.

Quickly just revisiting what I mentioned before with User.ChannelInfo.Index. I'd add that property because it's something that would play a part in the majority of programs that use your object. It provides a mean in which they can link a user to a specific number, and when done properly, the user implementing your object will synchronize that with the actual position they have stored in their channel list. This still separates the tiers, but provides a fast way for the presentation tier to match a user from it's channel list to a user in the application tier's userlist.
#13
.NET Platform / Re: Object Oriented Design Help
March 23, 2008, 06:59 AM
Firstly, I think what I'm saying is pretty accurate, but I may be wrong. Hopefully others will clarify any mistakes I make in this post.

A managed object is an object that's memory is handled by a garbage collector (in this case, .NET takes care of this for you, and automatically applies this to all the object's you instantiate). An unmanaged object is one that you have explicit control over it's memory, and it's up to you to free the memory when necessary.

The advantages of a managed object is that you don't have to worry about any of the million of things that could go wrong. The downfall is that you lose certain control and slight performance over that specific memory. The certain control you lose really only applies when doing relatively low-level things, or small tweaks and oddities that most programmers would never need to worry about. The slight loss of performance really only applies to those highly skilled programmers doing memory-intensive things as they'll be able to find optimizations. In most cases however, .NET is likely to handle the memory better than you could if you were doing it yourself, and the safety alone it provides you is brilliant.

Just a quick rundown of the safety about memory management so you have some idea of what I mean. When you use the 'new' keyword, it allocates a slot of memory (the size of whatever you allocated it for - i.e. Int32 would allocate 4 bytes[1]) in the 'heap'[2]. It then returns an address of where it's located (hence, by reference). The variable you assign this reference to is known as a pointer (it points to the address of where the memory is located). The dangers of this is that memory is now under your control. A pointer is simply a number (the address of the memory location). It tells you nothing about the size allocated. One of the major problems that occurs is that when parsing that pointer around, you may want to write to that section of the memory. If you write something longer than what was allocated (the size of the object/type you defined with 'new' for that pointer) is just writes over it. The memory outside the bound of your allocation could of been some very important data, another program may be relying on it, etc. This could to anything from a "lucky that's nothing important", to a slot that explorer.exe was using and a pretty blue screen. In case you're interested, this is where the terminology of words such as "buffer overflow, memory leaks, etc" come into play.

[1] - Technically, it creates slightly more than 4 bytes as it also has to create memory to store the address. On that note, you can't, nor would need to, determine the actual size it allocates. For things like structures and objects, even if it seems they have an explicit size to be allocated, padding is added.

[2] - Heap is an area of memory used for dynamic memory allocation. Not that this technical stuff matters to programming in VB.NET. I'm just clarifying the word.

The other issue with that memory is that once you've finished using it, you must free it (tell the computer you are no longer using it, so it can be allocated elsewhere). If your program crashes before you have the chance to free that memory, it will likely just sit there, wasted. In languages where memory is freed, if that memory was an instance of a class, the class' destructor (opposite of constructor - namely New() in VB.NET) is fired. This allows you to clean up a class, and possibly free any memory it may have allocated before it's removed. Now, this is where Dispose() comes in. In VB.NET, when an instance of a class goes out of scope, .NET flags it as unused, and eventually the garbage collector will free the memory. It doesn't instantly free it because there's no immediate need. Freeing memory does take processing time too, and .NET's memory management is designed in a way to free the memory at more appropriate times.

The idea of the IDisposable interface is to provide a standardized way of telling managed objects when they are no longer needed. This is important for objects that use unmanaged resources, or have things that need to be cleaned up immediately. The Using keyword comes into play to help you define the scope of an object's usage within your code. As you probably noticed from MyndFyre's post in this topic, the Dispose method is implicitly called at the end of a Using block. Hence a great example of the idea behind creating Interfaces for the use of standardization.

Now, in your code you set _userList, _shitList, and _safeList to 'Nothing'. Don't be fooled by that keyword. In Visual Basic 6 it would delete the object (free it's memory). But VB6 is an unmanaged language, unlike VB.NET which is managed. In VB6, when an object was deleted it would fire that object's destructor, which was the sub "Class_Terminate" within the .cls (class) file of that object. Or, for forms which where also objects in VB6, it would fire the sub "Form_Terminate" when you set the form to 'Nothing'. Note that if you set a form to 'Nothing' in VB6 before it was unloaded it wouldn't actually delete the object. Instead, it would just set the reference to the form to 'Nothing'. So any code you have interacting with the form would no longer work, yet, you could still access the form directly (like clicking on it). The form's destructor event was also only called when the form has been unloaded AND set to 'Nothing'. VB6 would automatically set form objects to 'Nothing' in most cases when all form's are unloaded, but sometimes it slipped up when the form was interacting with other objects and created all sorts of memory issues such as circular references, etc. Hence one of the reasons why you'd see so much code like this in VB6 programs:
Unload frmAbout
Unload frmMain
Set frmAbout = Nothing
Set frmmain = Nothing

Anyway, getting back on track. In VB.NET, setting something to 'Nothing' just changes what the reference to the object (being the variable) is treated as. It doesn't do any explicit memory freeing, nor does it even call the Dispose() method. When the object goes out of scope, it will be handled like any other dynamically allocated object through .NET's garbage collection.

Back in your code again, for that scenario, I don't think you'd need to implement IDisposable. As I said before, the idea of it is to provide a way of telling an object that it needs to clean up it's unmanaged resources. For example, connecting to a SQL Database to read/write a bunch of data, or opening a file to read/write a bunch of data, etc. Holding onto that connection, or keeping the file handle open until the garbage collection gets around will waste resources. It will also prevent that file being accessed until it's handle is closed. By implementing IDisposable in those cases creates an insurance that once you've finished working with them, they'll be freed up properly.



Going back to your original question: Determining what should be objects and how to properly design them.

Firstly, you gather all your ideas and such you want included in your bot class, and then start categorizing them. Categorizing works by defining precedence of needs. For example, the core bot object needs methods such as Connect and Disconnect, it also needs properties such as Username, Password, Client, and so on. Stuff like userlist, safelist, and shitlist are irrelevant at this point. So we put them aside for now. All we currently want to do is create a raw bot object. This object will be the overall [core bot] class, and further bot objects with more features will derive off it. This [core bot] object would be a derivative of the overall core [connection base] which you mentioned before.

To design the [core bot] object, it's easiest to start from the interface (not the Interface keyword). This interface initially consists of the public properties you would give it (this is assuming a project would directly interact with this object - as you develop them - the visibility of these public features may change into a protected).

Just off my head, I get some like this:

CoreBot (class)

  • Methods: Connect(), Disconnect(), State(), SendChatMessage(), SetProfile(), etc.
  • Shared Methods: NumberOfBotsConnected
  • Properties: Username(), Password(), Profile()[3], etc.
  • Events: Connected(), UserJoinedChannel(), etc. - Note that it's recommended you follow the standard of parsing the 'sender' and 'e' (EventArgs - you'd customize this) to the function.

[3] - I would create a Profile structure with Age, Sex, Location, and Description properties. Age would currently be ReadOnly(), and Sex would have checking as it's currently read only for StarCraft and BroodWar clients.

Essentially, once everything is outlined. [Core bot] would do nothing more than manage a connection with Battle.net mimicking a game client, and have no non-Battle.net features. It would derive from [connection base], and I'd recommand creating a few classes such as BNCS_Packets, BNLS_Packets, etc. These classes would handle methods for handling and sending every BNCS and BNLS respectively. They would have a property which you supply a reference to the packet buffer which your [core bot] is using, so they can directly create and send or manipulate the packet and parse the information back to you.

Note that although being a core class (core bot), and unlikely to be used directly. It should still follow proper encapsulation. Try to picture the object's public properties and methods like a bunch of textboxes and buttons a screen. Any combination of clicking on the buttons, or weird obscure input in the textboxes should be handled by the program. You should never expect the user to know these things. The idea behind this encapsulation is also that if the user does in fact mistreat the object, it throws an exception. It should never directly send a message to the user via a message box or the like. Hence one of the main concepts behind the object-orientated philosophy.

A note with your code, I wouldn't use a Try/Catch in a situation where I could prevent it. For example, you have:
Public Function GetUser(ByVal index As Integer) As String
    Try
        Return _userList(index).Username
    Catch ex As ArgumentOutOfRangeException
        Return "Out of bounds exception! The index supplied does not correspond to a user!" 'Is there a better way to do this?
    End Try
End Function


I'd change it to something like this:
Public Function GetUser(ByVal index As Integer) As String
    If (index >= 0) And (index < _userList.LongCount) Then
        Return _userList(index).Username
    Else
        Throw New ArgumentOutOfRangeException("index", "Out of bounds exception! The index supplied does not correspond to a user!")
    End If
End Function


Secondly, regarding your database. There is no need to over complicate things just because you can. The Tag class seems quite redundant and using lists of strings would do just fine. Remember, these lists aren't exposed directly, so there's no need to be overly safe by doing things such as "If value IsNot Nothing Then". That doesn't really add anything. The methods that are used for adding more users to these lists is the place for safeguarding and error handling to go. Though, with a list of the User class, you should still provide some error checking within it. And use the 'Throw' keyword as I demonstrated above to expel the error into the calling procedure rather than parsing it through the return value. The calling procedure would use a Try/Catch to pickup any of the errors that your User class may throw.

Another approach which would probably work more cleanly would just have a single userlist. In that userlist, each user would have properties such as Safelisted, Shitlisted, etc. This way your bot only has to loop through one list to determine all properties. This also will improve the efficiency of the bot, especially when it has to run a check on a bunch of users (such as when it joins a new channel). You could further combine the userlist to contain all the necessary details about the user in the channel (such as ping, position in listview, etc).

Also, why does your User class have a Password property? Here's some things I'd have for a User:

User (class)

  • Methods: LoadDatabase(filepath), SaveDatabase(filepath)
  • Properties: Username (string), Access (integer), Flags (integer) - would use an enumeration of the different flag types, each enum would be a power of two so they could be combined, IsSafelisted (boolean), IsShitlisted (boolean), InChannel (boolean), ChannelInfo (structure ChanInfo) - would contain sub-properties if InChannel is true

ChanInfo (structure)

  • Properties: Ping, Index (position in list/listview), Client (eClients - an enumeration of game clients), flags (integer - Battle.net flags), etc.

Now, although the property User.ChannelInfo.Index isn't required internally, it is handy to place this variable here as it allows the internal userlist to be tightly integrated with the users in the channel. The internal list shouldn't contact the external listview, but external code can access this value as fast method of grabbing user data from a channel list without the needs of further lookups. Small things like this can improve efficiency and help make things run smoother.

Ultimately the design of a project first comes down to what you want to do with it. You then think of things that may be done with the project. From that, you then look to see commonalities between code, or code that is rather generic. With this you can break it down into base classes, and use derivatives to define more specific features that the classes you want to use require. The more generic you can break a class down to, the more the reusability increases. Taking this into consideration, you shouldn't be excessively trying to break things down too far, such as your Tag class just to hold a single String.

Hopefully this post provides more information than it does exaggeration. I tried to explain things in fair detail so you can understand the reasoning behind them. :)
#14
Quote from: Andy on March 09, 2008, 06:02 AM
How does one determine the number of users in games...?
It tells you when you login to Battle.net in that info stuff.
#15
I just picked up on one thing that may benefit your code. You could use the two Winsock API functions htons() and htonl(). They stand for Host to Network Byte Order (Short/Long). Which basically converts a short (16-bit) / long (32-bit) to big endian.

Public Declare Function htonl Lib "ws2_32.dll" (ByVal hostlong As Long) As Long
Public Declare Function htons Lib "ws2_32.dll" (ByVal hostshort As Integer) As Integer


Also, I don't remember much about this. But when using CopyMemory() on strings in VB6, do you need to convert them to and from Unicode?

strAscii = Format(strUnicode, vbFromUnicode)
strUnicode = Format(strAscii, vbUnicode)