The official forum for the The Heretic Mansion Fusion Chart application
You are not logged in.
Hi,
I have a simple question for you: are you working on a Persona (fusion helper) program as well? You see, I'm already working on one, and posted on GameFAQs for some help, and a user redirected me to you to ask you about this. Even though I will still continue making my program regardless of this, I thought it wouldn't be a bad idea to ask.
You can find more details about this on this GameFAQs thread I made.
If you can also participate in that thread, or if you can give me suggestions/opinions about the program in this thread, that would be marvelous. ![]()
Thanks for your time! ![]()
Offline
Hi,
Sorry about the late reply. Currently, I don't have any plans but I'd be glad to offer any help I could although my programming skills aren't top notch when it comes to desktop applications. ![]()
The .NET framework was the only reason I had the guts to make an application such as the Heretic Mansion. It's indeed a marvelous piece of work!
Eitherway, I don't even have Persona so you get the idea ![]()
Offline
Hi! ![]()
It's okay, I figured you probably aren't checking this board very often because there's not much activity going on here very often.
Well, like I said in the GameFAQs thread I mentioned earlier (I also replied to your post there, btw), the only thing I can think of that I need help with is the design part, and mostly in the form of suggestions or tips.
However, there's one thing that's been bugging me, and that's how would I use SQLite in my app if I wanted to. Right now, I'm using my own objects to store the information (e.g.: TPersona, TEvolvedPersona, TSkills; T standing for "Type"). Accessing fields right now is pretty simple (e.g.: Persona1.Level to get the level), and passing an object to a function is also simple (like passing Persona1 and Persona2 to a function that returns the resultant Persona [as an object, of course] of a normal fusion between the two), but how would I do that using a SQLite? How would I query the database for a field of a particular Persona, and how would I pass the information I need to a function (the information I need usually being all the fields I store right now in the objects I created, such as Level and Skills [which are pointers to the actual skills that are stored some place else, to avoid redundancy])?
Like I said, I'm not used to making apps that communicate with databases, so I have no clue on how to implement the stuff I need this way.
Oh yeah, one other thing I would like clarification on. I read a lot about Mono after you gave me that hint, and I like it very much, but is Mono able to run applications built on Windows for the (Microsoft) .NET platform, even if those applications weren't made with the thought of working in Mono? I can't seem to find a clear answer to this in their FAQs, but from what I read, I have to recompile my code in Mono if I want something like that, right?
Well then, if you aren't making a program for it, then all the more reasons for me to develop this program, I guess. ![]()
Last edited by Cloud737 (2009-07-20 16:07:43)
Offline
The Heretic Mansion also uses the same concept. Each demon is represented by an object of type Demon (which I defined of course). You can access his attributes like Demon.HP, Demon.Str, Demon.Family, etc. It's just that you have to get these data from the database.
In order to use SQLite (or any other RDBMS), you have to think of it as means of storing data in the most efficient way. Meaning that how you can connect the data found in Table 1 with the data related in Table 2. You don't want to have the data to be repeated over and over. Redundancy such as having the demon's family name for example repeated for many times is not good for many reasons (think if you had to rename the family, how many rows are you going to modify). So instead you split the info into another table. How you represent this data is part of the application design.
Take for example a table containing the demon details. Let me show you an actual example of these two tables structures:
Demon:
id
name
family_id
Family:
id
name
So you simply link Family.id with Demon.family_id when querying the database and to translate this into SQL it would look like:
SELECT Demon.*, Family.name FROM Demon, Family WHERE Demon.family_id = Family.id;
This way, I get to keep the family name once instead of repeating it on every demon's record.
As for Fusion, it follows the same thing, The Heretic Mansion's fusion table is among the smallest tables:
Fusion_Normal:
first_family_id
second_family_id
result_family_id
As simple as that! It says if family 1 was merged with family 2, what will be the resultant family. Finding out which demon in the resultant family is found with a formula that is part of the application's job not the database. Otherwise, you will be hardcoding the data in the database and you application becomes rigid and not as robust and flexible. You will be ending up with a bloated database that didn't use the features of RDBMS (e.g. Joins, Unions, etc) that made it exist in the first place.
Say you wanted to find all demons that have a particular skill with table structures as follows:
Demon:
id
name
family_id
Spells:
id
name
Demon_spells:
demon_id
spell_id
Demon is the same as above, Spells contains all the spells in the game, Demon_spells links the previous two together.
the SQL to find all demons with, say, Spell Agi (with ID=13) is as follows:
SELECT Demon.name FROM Demon, Demon_spells WHERE Demon.id = Demon_spells.demon_id AND Demon_spells.spell_id = 13;
It's very straight forward. You can even implement sorting. Say you wanted to sort by level, you simply append the follow to the code above:
ORDER BY Demon.Level ASC; // or you could use DESC for descending order
To initiate a Demon object (not Demon Table, it's fixed) in HM application, I simply pass the demon ID to the object and the object will fetch all relevant data for me (of course I had to program the logic).
Here is a glimpse of the actual code in HM:
public void setDemonInfo(int ID)
{
string sqlQuery = "SELECT d.*, f.name AS familyName " +
"FROM demons AS d, families AS f " +
"WHERE d.family = f.ID AND d.ID = " + ID.ToString();
using (SQLiteCommand com = new SQLiteCommand(sqlQuery, this.db))
{
this.db.Open();
using (SQLiteDataReader rd = com.ExecuteReader())
{
rd.Read();
this.ID = Convert.ToInt32(rd["ID"]); // Demon ID
this.name = rd["name"].ToString(); // Demon Name
this.level = Convert.ToInt32(rd["level"]); // Demon Level
this.family = rd["familyName"].ToString(); // Family Name
this.family_id = Convert.ToInt32(rd["family"]); // Family ID
this.str = Convert.ToInt32(rd["str"]); // Strength
this.ma = Convert.ToInt32(rd["ma"]); // Magic
this.vi = Convert.ToInt32(rd["vi"]); // Vitality
this.agi = Convert.ToInt32(rd["agi"]); // Agility
this.lu = Convert.ToInt32(rd["lu"]); // Luck
this.hp = (this.level + this.vi) * 6; // Hit Points (HP)
this.mp = (this.level + this.ma) * 3; // Magic Points (MP)
setScreenshot(rd["screenshot"]); // Screenshot
}
}
calculateSummonCost(); // Summon Cost
}This method is called within the constructor to initiate everything so I may call Demon.level or Demon.agi or whatever without recalling the database again.
Offline
As for Mono, according to Mono's website, if your application is using .NET components (Windows.Forms for presentation among others), then recompiling should not bring any issues for most applications.
From their website:
Whereas the .Net implementation is a binding to the Win32 toolkit, the Mono implementation is written in C# to allow it to work on multiple platforms. Most of the Windows.Forms API will work on Mono, however some applications (and especially third party controls) occasionally bypass the API and P/Invoke straight to the Win32 API. These calls will likely have to changed to work on Mono.
Yes, you will have to recompile your C# application in mono to have it run cross platform.
Actually, I might give it a try myself for the Heretic Mansion but I think the SQLite library might give me some problems.
EDIT: Actually, You do NOT need to recompile your applications to run on Mono! You just have to make sure that the code is compatible with Mono. There is a Mono Migration Analyzer to help you find out if your code is not compatible with Mono.
Offline
Ah, I see now. I thought that would have to query the database every time I needed something (or improvise my own method of transferring the data in the database to my objects), which would be a pain. So, basically, all I'd have to do is replace just the reading from and writing to a file mechanism, and everything else would be the same. Sweet! ![]()
I know what you mean about storing data in an efficient way, and avoiding redundancies. Like I said, I studied SQL and databases in high-school when we were taught about Oracle databases. Haha, never would I thought this would actually come in handy so soon.
It's really surprising for me that I understood all the code and concepts there, I thought that I would at least have forgotten some.
Yeah, I understand exactly what you mean about storing only the resultant families and just calculating the resultant Demon when needed, since that is exactly what I am doing with my program. It's especially important since I can't make it flexible enough to work with Persona 3 and Persona 4 if I hardcode what Persona is the result of what, as these things change between games (since some Personas change arcanas, levels, etc. and it even has new Personas in the mix).
Hey, I'm curious, after opening the database, is all the data in the database loaded in memory, or is just read from the disk when needed? I ask this since I'm thinking of using it after I loaded the data into my objects, like for sorting the data in my grids, and then finding out which object corresponds to the row selected in the grid by comparing IDs. If the data I need is read from disk each and every time I ask for it, then the performance penalty would be quite substantial if I would to do this more than once for the same data.
Yeah, I've read that part too, though the problem is that I'm using a language that the .NET (development) architecture itself doesn't support (the devs at CodeGear, who made Delphi, implemented their own .NET compiler and IDE to add this support), and I'm also probably using components specific for the Delphi version of .NET (as in I'm not using components that are in the .NET development architecture, but those that were made by CodeGear that would only work on their own IDE).
Sigh... I was hoping for an easy way out by having Mono automagically "emulate" .NET so applications would work without recompiling, but I kinda expected this after reading their website, though I wasn't 100% sure that was the case.
Anyway, half the problem is probably solved since I've seen a plugin for Mono that let's me use the Object Pascal (aka Delphi) language, now it's time to see what I can do with the components, but that will come after I release the Win32 version of it.
Thank you very much for your help! I'm actually thinking of implementing SQLite now since it will make my life a lot easier (not only the sorting part, but also the part where I'd have to display information from multiple "lists", not necessarily one at a time, which is a major concern for me right now, as I really have no clue of an easy way of implementing this, bar SQLite, of course). I'm actually pretty excited and giddy since I'll be able to apply knowledge that I never thought I will ever be given the chance to apply, and it'll also make my program more professional. I'll try and see if and how I can implement it, and I will keep you updated on my progress.
Oh, and I agree we should keep the techical talk here. I was actually thinking of proposing that in my last post, but somehow, it just skipped my mind when writing the actual post.
Also, the mother of all languages isn't C, it's assembler.
Actually, I think the true mother of all languages is machine code, since that's where everything, including assembler, came. You can't get any more raw and crude than that! Not very readable, of course, but it definitely can give you raw metal power when you need it.
And I agree that each program is as readable as the programmer wanted it to be, but that same program (as in same sequence of concepts) may be more or less readable in another language than the original. For example, in Delphi, a constructor is written as
constructor Create (list of parameters: parameters type);
It's pretty obvious what that method would be, as opposed to C++ where if you don't know the constructor shares the same name as the class it is for, you won't be able to find it.
Another example would be how pointers are expressed, especially when they're pointers to objects. For example, how would you interpret *pointer.field in C++, where pointer is a pointer to an object? The logical assumption, if you don't know better, would be (*pointer).field, but in reality the "." operator has greater priority, so it's like *(pointer.field), which of course will produce an error. In Delphi, the dereference operator is post-fixed, as in it's after the pointer variable, avoiding the whole interpreting mess that is in C, and it would be written as pointer^.field, where "^" is the dereference operator (and it would be Object.PointerField^ if you want to dereference a pointer that is a field of an object). Actually, Delphi has gone one step further in making the "." operator handle dereferencing as well, so the same thing could also be written as pointer.field without a problem if you wish, and it's much more convenient than the "->" operator used in C for dereferencing if needed and accessing object fields.
Do you see now why I mean that the language is more readable (and thus less error-prone) than other languages? There are of course many other things that make it more readable, but it would take too long to list them. If you want, I'll give you the source code to my project to see what I mean, or you could wait till I release it (along with the source code).
Anyway, sorry for the long post. I guess I'm a bit chatty. ![]()
Offline
Hey, I'm curious, after opening the database, is all the data in the database loaded in memory, or is just read from the disk when needed? I ask this since I'm thinking of using it after I loaded the data into my objects, like for sorting the data in my grids, and then finding out which object corresponds to the row selected in the grid by comparing IDs. If the data I need is read from disk each and every time I ask for it, then the performance penalty would be quite substantial if I would to do this more than once for the same data.
How you load your data is up to you and no, not the whole database get loaded otherwise, again, we are defying the usefulness of RDMBS. Only the "SELECT"ed values are loaded.
As for sorting, what I did was loading all the data I wanted into a ComboBox component and use the sorting methods that are built within the component it self! So no more querying the database unless new data is needed. My strategy was always to load all the data I need in the best way and further manipulation is done on memory. As for performance, don't you worry about that!
SQLite is pretty fast and the data you are loading is very small so no worries.
In HM, the ComboBox contained the demon name and its ID, when it's selected, I query database for all the remaining data. I bet you didn't even notice any performance issues, did you?
Of course I could load the whole database into memory but the idea itself stinks and doesn't sound right.
Offline