iPlayer, ePlayer... what do the i and e mean?

enum I believe.
 
It's origins are here - http://en.wikipedia.org/wiki/Hungarian_notation - but it has been seriously abused and misused over the years - to the point where unless you know what the original programmer meant, it's pretty much useless.
 
Despite all the misuse, though, hungarian notation is still a seriously good idea for readability of your code. Admittedly, perhaps not a vital one, but it will really help you out when working on big projects.

One just has to remember to be consistent.
 
The "e" prefix stands indeed for "enum" but in civ5 they are just integers. So iPlayer is the same as ePlayer, they are both the player ID. Just as iResource, eResource, resourceID and resourceType are all the resource ID (and not the resource type. Actually all "~type" in the API are ID and not types, which is a very stupid naming). Firaxis seems to hate naming conventions.

Civ5 API cheatsheet:
* pFeature = Object
* iFeature, eFeature, featureID, featureType = ID
* feature = Maybe an ID, maybe an object.

More confusing things:
* It works: for i = 0, pPlot:GetNumUnits() - 1 do pUnit = pPlot:GetUnitByID(i) end
* It doesn't work: for i = 0, pPlayer:GetNumUnits() - 1 do pUnit = pPlayer:GetUnitByID(i) end

The reason? Because pPlot.GetUnitByID expects a plot-dependant index (the index of the unit on this very plot) while pPlayer:GetUnitByID expects a global ID, as returned by pUnit:GetID() (those IDs are spreaded among civlizations). You actually have to use pPlayer:Units(), I learned that the hard way! And finally pPlayer:GetCityByID also works differently since it expects a player-dependant index but it can still return nil cities (deleted cities), while pCity:GetID() returns a player-dependant index.
 
The hungarian notation is not terribly helpful for Civ code. It tells you things you don't need (why say iX, iY when x, y are perfectly clear?) and sort of encourages you to make things ambiguous that should not be ambiguous (DonQuiche's iUnit example above). And Firaxis' inconsistency makes matters worse. But if you are writing >1000 lines of Lua you should develop and follow your own standard for your own sanity.

Not to say mine is better than anyone else's, but take it as a possible example:

_____ID always refers to a table row ID (integer)
_____Type always refers to a table row Type (text)
_____Row always refers to a table row (which is a table)
i_____ always to an object index and never a row ID. E.g., iPlot, iPlayer, iTeam, iCity, iUnit, (just have to remember that iCity and iUnit are by player and not unique across the game)

Constants are all uppercase. Objects and anything else are always just lower case (or "camel case"). There is no ambiguity here because the number of object types is not that great and we all know them: plot, unit, player, team, teamTech, etc. Something like "unitIndexForPlot" makes it quite clear that this value is an integer and different than "iUnit".

Thalassicus has a nice discussion on this here.
 
why say iX, iY when x, y are perfectly clear?

1> Because single-letter variables are much harder to grep for. Long ago I learned that loop indices were best named "ii", "jj", "kk" etc., unless some more descriptive name was available. Basically, when debugging you want something you can search for without hitting a bunch of false positives.
1a> While a more descriptive loop index may seem like a good idea, that makes it much easier to confuse your loop indices (which are only modified by the FOR commands) with other variables that can be modified by your logic. If you're not careful with this you can easily get stuck in an infinite loop.

2> Because "x" and "y" might be structures or arrays. Especially X; in many programming languages or conventions, X is used as a positional vector, with x[0] being one axis, x[1] being another, and so on. "iX" makes it clear that it's a single integer value being stored.

3> Because some programming languages use implicit typing of variables. Unless specified otherwise, a variable in FORTRAN is an integer if its first letter is I through N, and a float otherwise. (Competent FORTRAN programmers use the "IMPLICIT NONE" command to ensure this doesn't happen, but I've debugged far too many routines written by people who didn't bother.)
Civ5's map x and y values are always integers, because the map is made up of hexes, with no room for fractional values. Therefore, a programmer who learned his skills in those earlier languages would prefer to use the "iX" nomenclature, since "X" would imply a real value.
 
Competent FORTRAN programmers use the "IMPLICIT NONE" command to ensure this doesn't happen, but I've debugged far too many routines written by people who didn't bother.
It is because very few Fortran programmers are competent ones: most of Fortran programmers commit suicide before they become competent. If I had a worst enemy, I would force him to program in Fortran (will full compliance to Fortran 66 of course).
 
If I had a worst enemy, I would force him to program in Fortran (will full compliance to Fortran 66 of course).

Pfft, you're too soft. Go back to BEFORE the '66 standard if you want to be really cruel. But yeah, the old versions were really horrible, with limits like 6-letter routine names (and no capitalization or punctuation allowed) and really rigid spacing rules.

My first programming job after college was for a defense contractor that was trying to update some old 77 code to the 90 standard. (This was in 1996, so the 95 update hadn't really been adopted yet.) My initial role was to switch all of the common blocks to modules, make the large arrays into allocatable structures, and so on. My unofficial second role, though, was in debugging the sloppy code written by "experts" who had plenty of scientific expertise but no programming skills, so my comments about "IMPLICIT NONE" were based on personal experience.

And FORTRAN wasn't so bad. It was painful at first, but you quickly learned how to program in an environment that wasn't object-oriented, which is a handy skill to have since most script-based pseudo-languages (including things like Lua) share more commonalities with FORTRAN than they do with a more robust C++-type language. I just wish we had better debugging tools to work with...
 
It had never occurred to me to make my mod Fortran compliant.

But seriously, none of this has any bearing on Civ5 modding. The only possible confusion about "x, y" are whether we are talking rectangular or hex coordinates, but hungarian notation doesn't help at all with that. It's just ugly clutter (as are superfluous semicolons).
 
It had never occurred to me to make my mod Fortran compliant.

Don't be ridiculous; it's not about making your mod compatible with another language. It's that if the person writing the code is an actual programmer and not just someone playing around, then they'll try to use practices that are Good Coding Practices for all languages, and not just develop habits (usually bad ones) based solely on the particular language/scripting set they're working with at the moment. That's why those notation conventions are useful; even if the particulars of the language in question don't NEED to follow that convention, the person working on it is going to move on to some other language in a year's time, and it's better if he's not changing his habits as he goes. I've learned a good 20 programming languages or pseudo-language scripting sets over the past couple decades, and if I altered my habits for each one I'd never get a job. I'm guessing, then, that most of the folks who programmed Civ5 are actual honest-to-god programmers who've cut their teeth on languages a bit more advanced than Lua, and so have learned to follow naming conventions for all of those reasons I mentioned.

Besides, those other two things I mentioned ARE still valid, even if you want to ignore the Fortran bit. I'm at work right now, and as we speak, I'm debugging code that consistently uses "x" as a 2-dimensional positional array, instead of explicit X and Y values, because that's how we astronomer-types deal with large amounts of 2-dimensional image data. A lot of my internal variables begin with "i", "n", "s", and so on to designate whether they're an index, counter, or structure. And all of my loop indices are named "ii", "jj", "xx", "yy", and so on, for exactly the reasons I listed above.
If it's all code I've written for myself then there's not an issue, and I could name the variables whatever I want, but if I'm going to hand this code off to someone else, it's better if we're on the same page for notations.
 
I'd just been guessing that "i" was in reference to an index, "p" a player and so on, but have to admit to complete ignorance and looking at it as intuitively as I could.

pPlayer = player in question

pOtherPlayer = players that are not the player in question

Etc.

Once or twice, I've had to remind myself that the "player in question" is dependent on the references being made and their relationship(s) with other references, when it comes to figuring out logical arguments.
 
I know it's a somewhat old thread, but I stumbled across it and figured I'd add my thoughts.

One very important thing when adding to an existing code base is consistency. However, I've counted 6 different variable naming schemes in the Firaxis code, so there is no standard to follow. My advice for programmers is therefore to pick either camel case (variableName) or hungarian notation (bVariableName), whichever you feel most comfortable with, and consistently stick to it. Those are the two industry standards for variable names.

I personally use camel case because I find player & playerID easier to read at a glance than ePlayer & iPlayer. The first pair has more visual differences.

The most important things are being consistent, and using variable names which actually identify their purpose. I've seen far too much cryptic code like this from programmers:

Code:
if cT ~= "" then
  repeat
  local t1, t2; local more = false;
  s, e, c, d = findToken( cT, e );
  if s ~= nil then t1 = deserialize( c ); end
  if d == "=" then
    s, e, c, d = findToken( cT, e+2 );
    if s ~= nil then t2 = deserialize( c ); end
  end
  if d == "," then e = e+2; more = true; end
  if t2 ~= nil then r[t1] = t2;
  else table.insert( r, t1 );
  end
  until e >= len and not more;
end
 
In civ, you're going to encounter s and p most often. s is a static thing, that is, something that doesn't change. sCat = pMittens. p is supposed to mean pointer, which is kinda how it's used in Civ Lua. Basically, if your variable points to a specific thing, like a Player, a City, a Plot, or whatever else, then it should be prefixed with a p.

Lastly, remember that it's not what your variable is, it's what it's for. If you're going to use it like an integer, name it i or n. You get the picture.
 
Is there any convention out there for file locals versus globals (or what passes for global in our Lua sandbox)? I see Firaxis generally uses g_ for file locals -- "global at the file level", I guess. I sometimes see m_ but I'm not sure what they are using that for. I've been using g_ for both file locals and mod globals, but that's starting to get confusing so I'd like to make the distinction in my variable names.
 
I believe everything in lua is restricted to the file level unless you include one file in another, or attach a variable to a global table like Game or MapModData.

m_ is short for "my". In c++ it's common to prefix data members of a class with "my." I prefer the "myVariable" format instead of "m_Variable" or "g_Variable" because it fits the standard camelCase format. I strongly recommend sticking to either Hungarian notation or camelCase (whichever you prefer), and do not use underscores in variable names unless you are declaring an uppercase constant like CONST_PI = 3.14159. The programmers for Civ 5 frequently deviated from standard coding practices, which makes their code harder to change and debug, so it is not a good example to follow.
 
Back
Top Bottom