« first day (208 days earlier)      last day (3652 days later) » 

10:09
hey
10:45
heh, found a nice "bug", just a theoretical one for now in HearthMonitor
If you name your player GameEntity, then the log reader will break down
3
 
3 hours later…
13:42
@skiwi New game account in creation :P
@Marc-Andre lol
14:44
Monking
15:04
monking @Phrancis !
I'll check it out... @Duga must be asleep :)
Yeah that is what I thought! This is why I posted it myself!
It's a neat idea, I think it wouldn't hurt to explore single-player options a bit more, not everyone is into playing online all the time (and right now, often there are no people playing lol)
15:24
AHaahah
15:35
@Marc-Andre it would be really awesome if the game allowed for a team of players to fight against bosses
@bazola Nice option to explore ! I like it!
it would be easier to balance hero power type abilities against PVE encounters than PVP i think
I guess too! At least you control one side of the encounter!
one player could have a stun (unit loses a turn), another player have a silence, maybe even a taunt type ability (give a unit taunt for a turn or permanently)
16:15
I could certainly see a mod based on team play like that
this is easy with lambdas, but how do I do it without them? @skiwi @SimonAndréForsberg
    for (Resource.Type type : resourcesToDraw) {

        TextButton nextButton = new TextButton("Sell", skin);
        nextButton.addListener(new ClickListener() {
            @Override
            public void clicked(InputEvent event, float x, float y) {
                MyScreen.this.playerSoldResource(type);
            }
        });
16:34
What's the downside of doing it with lambdas?
doesn't work with libGDX
its looking like i could do something like this and pass in the argument that I need:
public class MyClickListener implements ClickListener{
    Label info;
    public MyClickListener(Label info){
        this.info = info;
    }
    public void clicked(InputEvent event, float x, float y) {
        Gdx.app.log("button","clicked");
        info.setText(Integer.toString(i));
    };
}
I almost understand what this is doing... lol.
I do find the name MyClickListener to be a bit odd, is that common to name things with possessives?
@Phrancis its just example code from stack overflow
16:44
Oh ok
Well, time to do some more game balancing :D
solved it:
Nicely done!
That game of yours is getting better-looking by the day
I'm testing out Rush cards for balancing... Modleg Ambusher is a very good card, it needs to cost a bit more
17:01
this is what I needed to do to pass an argument into the ClickListener:
	class ResourceClickListener extends ClickListener {
		Resource.Type resourceType;
		public ResourceClickListener(Resource.Type type) {
			this.resourceType = type;
		}
	}
17:12
Hey @bazola what is the tower-like structure to the right of the character?
@Phrancis capital city
Does that open up a different map (e.g., "the city"), or is it a structure you interact with for resources and such?
right now you will be able to trade resources with it in the same way that you trade resources with a trading post, but by trading enough resources you will gain influence over the city and it will count towards your total number of tiles in that region
Ahhh that's a neat mechanism
Man I'd love to try that game once you have a playable release!
@SimonAndréForsberg Got a question about the phrancis-cards.cards file
(or to be more precise, the way the client displays something related to the cards)
I modified this card:
[entity]
name=The Chopper
manaCost=2
attack=2
apply:health:1
scrap=1
sickness=0
apply:creature:"Mech"
It originally had sickness=1 but I set it to 0 to make it have Rush
(I have done this on other cards as well, like "Spareparts")
So it does not display the "Rush" property for that card in particular... I'm about to test in game to see if it works as if it had Rush
[entity]
name=Spareparts
apply:creature:"Mech"
attack=0
apply:health:1
scrap=3
manaCost=0
sickness=0
They both appear to be formatted correctly
17:40
@Phrancis move apply:creature:"Mech" up, below the name. apply:creature sets sickness to 1.
Ahhh
I didn't know the order of the properties mattered
Are there any other little quirks like that I should know about the card loader? (so I can document it)
Do you think by convention all the apply: type of properties should be declared before the other properties?
that might be advantegous, yes. although apply:creature is most important
@Duga is on strike btw. (@Marc-Andre)
OK I'll refactor the phrancis-cards.cards file and add documentation.
Yeah stats.zomis.net/io-web is down too since it's running on the same tomcat I presume
@Marc-Andre yeah, @Duga got sick and shut down the whole tomcat service.
17:49
Are you hosting it yourself ?
18:08
##### CONVENTIONS
#
### It is highly recommended to use the following conventions to avoid unexpected game behavior or bugs.
#
# * Always put the apply:creature or apply:enchantment property at the beginning of each card entity, just below the name property.
#     - An example of a bug that failing to do this does cause is if you set sickness=0 and then
#       declare apply:creature afterwards, when the entity is parsed apply:creature will set sickness=1 automatically,
#       negating the effect of previously declared sickness=0.
@Simon does this documentation look good to you?
aaand bakc
@SimonAndréForsberg what's the status on your *.cards file? Is it intended to be there forever, or just as temp?
As I worked and finished the card loader a while ago, but I know it doesn't support effects yet
18:26
@Phrancis looks good
@skiwi honestly, don't know. just wanted an easy way to add some effects and let @Phrancis play around a bit more.
@skiwi the XML card loader does not support effects.
I see
there's still point in continuing that path then and convert @Phrancis files some day
As far as I'm concerned, I think using a plain *.cards file is a simple and practical enough way to load and change cards for a while
can also make a custom format for that if you want, but still use the card loader mechanism
Anything more complex than that would kind of feel like YAGNI at the current time, much rather us spend time developing the server & client than worrying about how to load cards
<lunch>
and defining the effects will most likely be done in Java/Javascript/whateverscript, though they should be referable for example by id and parameter values
18:30
@skiwi technically, my card loader for the *.cards files is using the interface you built.
@SimonAndréForsberg Then that's even better :)
The effects loader idea is still such that you give them an id and can refer to them vrom the card loader
@skiwi at the moment, using apply:xxxx in a *.cards file uses reflection to scan the mod class used for methods named xxxx, and calls them (with string / int parameters, if specified)
@SimonAndréForsberg hack, but it works
@skiwi all approaches I have in mind for that "effects" feature would use reflection.
The approach I had in mind a while ago was to create a class for each effect and have it implement some interface
@Phrancis wouldn't necessarily need to create the effects himself, though he can do so if it's not too complicated
18:39
@skiwi that'd be a whole bunch of classes! I'd prefer each effect to have a method instead
First up is fixing my HearthMonitor, running into difficulties...
@SimonAndréForsberg That'd be a whole bunch of methods!
Both ways would work I suppose
though methods seems to rely more on annotations, whereas classes can rely on implementing interfaces
Do you have a minute to be my rubberduck for an issue in HearthMonitor?
@skiwi there's no need to rely on annotations (at least not at the moment). and methods can rely on interfaces as well (they can return an interface! - which is what they are already doing in fact)
@skiwi QUACK!
@SimonAndréForsberg Hm ok, that makes sense
@SimonAndréForsberg I've got a bunch of tag change events, like the following:
[Power] GameState.DebugPrintPower() - TAG_CHANGE Entity=skiwi tag=PLAYER_ID value=1
[Power] GameState.DebugPrintPower() - TAG_CHANGE Entity=skiwi tag=TEAM_ID value=1
[Power] GameState.DebugPrintPower() - TAG_CHANGE Entity=skiwi tag=ZONE value=PLAY
[Power] GameState.DebugPrintPower() - TAG_CHANGE Entity=skiwi tag=CONTROLLER value=1
[Power] GameState.DebugPrintPower() - TAG_CHANGE Entity=skiwi tag=ENTITY_ID value=2
My problem at hand is that they refer to Entity=skiwi, there's no other information known
So all I can do for the first message is to save it "somewhere" for Entity=skiwi
then at the bottom I know ENTITY_ID = 2, so I can grab the entity from the ECS interface, and then I can create the Entity=skiwi <-> ENTITY_ID=2 connection
and whenever it sees an upcoming Entity=skiwi message, then it will need to find that connection/reference
Does that seem logical?
In the case of cards the Entity=... lists the card entity id, so then it's easy
18:45
quackk
@skiwi quack quack quack? quack? quack.
3
You may talk now :)
(translated from DuckSpeak: Yes, that seems logical)
Think about it, is there even any other way you could do it?
I'm not able to see another way
All I can do to store the information globally is to create some Entity in the ECSGame that only stores the player name there? And the values
Me neither.
@skiwi or you could use a HashMap somewhere in your reading methods?
@SimonAndréForsberg The only shared state is the ECSGame instance, if I don't want to resort to static variable black magic
18:52
@skiwi ECSGame it is then!
unless you add some ParserContext class yourself that you pass around?
@SimonAndréForsberg that would be difficult I think
The ugly part now is that every parse command needs to have support for this
@skiwi then how can you share the ECSGame instance? Don't you pass that around as well?
@SimonAndréForsberg That one I do pass around
</lunch>
Ah hmm, you mean I also pass around other stuff there
Would that be better than shoehorning stuff into the ECS?
18:59
@skiwi instead of passing around ECSGame, pass around a ParserContext that includes both the ECSGame and other stuff you might need.
luckily, you only need to make this change once, then you can add whatever you want to the ParserContext
That's quite a major change, but a good one I think
@skiwi in my opinion, yes.
private static final Map<Class<?>, BiFunction<CommandContext, LogEntry, Command>> COMMAND_MAP = new HashMap<>();
It is, then ^
will need more refactoring one day
So I can use the CommandContext as my sort of utility class, even better @SimonAndréForsberg!
19:16
when you all talk about returning an interface from a method, what would be the point of doing so? what is an interface except for just a list of public properties and methods for a class?
@bazola It's a return type for the caller
Imagine a method returning ArrayList<T> or List<T>
Not sure if this makes sense here
But why would you return an ArrayList<T> if you do not care about the fact that it's in arraylist and has O(1) access time? You could as well return a List<T>
hmm
@bazola Well if you return the interface, you can modify the implementation without modifying the calling cde.
@Marc-Andre by changing where the interface points to?
imagine public List<> vs public ArrayList
if you return List, you can use ALL the classes that implements List in your method without modifying the signature of the method
if you use public ArrayList, well if you need something else you need to change the signature. Changing a signature means modifying the calling code
If you use implementation and I use your code, I'm dependent on it. You change it, you break my code. If you use an interface, I don't need to modify anything (unless you decide to change the interface you use)
Does it make sense now @bazola ?
19:26
I might have a meaningful example now
Consider:
public ArrayList<T> someMethod() {
    return new ArrayList<>(); //internal implementation performs best on ArrayList<T>
}
People calling this method can do two different things:
1. `List<T> list = someMethod(); //the "correct" way if they do not have an advantage in known that it returns an ArrayList<T>`
2. `ArrayList<T> list = someMethod(); //the "wrong" way, they don't need to know it's an ArrayList<T>`
That's why you always need to code against interfaces if it makes sense
Now after some time you decide that someMethod() should internally use a LinkedList<T>
public LinkedList<T> someMethod() {
    return new LinkedList<>(); //internal implementation performs best with LinkedList<T>
}
The one who assigned someMethod() to List<T> will still be fine, but it will break down for the one who assigned it to ArrayList<T>
now as library maintainer (maintainer of the someMethod()) if you want to keep compatibility you can do nothing else but to use the old version or to use the new version and then take the take from the LinkedList<T> and return it in an ArrayList<T>
If you use List<T> as return type, you can always change the implementation
19:43
that does make sense, and I suppose it is dependent upon List and ArrayList and LinkedList all having the same interface?
@bazola Indeed, ArrayList and LinkedList both implement List
but the same principle is true for all interface
so in the above example, when you call for List<T> = someMethod() vs ArrayList<T> = someMethod(), it is the interface of List that is handling which one you get?
@skiwi static? Wtf?
19:58
AI Fighter played those 3 ranged cards all on the same turn, interesting move
@bazola each effect is an instance of an interface. When using streams and stuff, predicates and suppliers and functions are also instances of an interface. In Cardshifter, this essentially means that theoretically we can make something like creature.apply(addTrigger(heal(1))) (just as an example, this means "give creature 'heal 1 at end of turn' ")
@SimonAndréForsberg Would the AI know about the new reload turn handicap on Ranged cards, and play them all at once so they could all synchronize their attacks on the same turn?
Or this is pure coincidence?
@SimonAndréForsberg when something is an instance of an interface, how does it know which implementation to go to?
@bazola The main advantage of returning an interface from a method is not just that you can change the implementation more easily, it is also that you can change the method you are calling. If you have 100 methods that return an instance of EffectComponent, then you have 100 different Card Effects to choose from!
Using the interface is just a facade. Your object is still an ArrayList<> but you don't have access to all the particular method of ArrayList<> since you're using it as a List<>. It knows which implementation to use since the actual object is a ArrayList (in the exemple we have gave you earlier)
20:05
@bazola if you have an instance of an interface, that instance is an implementation
@Phrancis nope, it has no idea about that.
@SimonAndréForsberg @Marc-Andre ah, okay, it is becoming clearer now.
@Phrancis I guess the AI just calculated MANA vs Cards Cost and determine it could played all the cards in the same turn and that it would give it an edge I guess
I'm not sure it's programmed to plan ahead of time for moves like that?
i appreciate the help. There are similar things in objective-c but I have usually set things up differently, or haven't had the need in my own code to use interfaces as much
(then again, it could be, Simon made it after all)
20:10
@bazola It still useful to use it in your own code. You just define what it;s suppose to do and then BOOOM you can change how you did it as you wish
20:22
@SimonAndréForsberg Uh... yeah, that still needs a refactoring, especially as I'm using that same map on two different places
21:19
I feel like I cannot push until the code and result is in a better shape as the last pushed commit... so it'll have to wait
lol
My Tirion Fordring is so good that when I execute a full game, and then rewind it to the start, it doesn't want to leave the field anymore
21:39
This feels a bit hack-ish
I need to execute commands twice in some occasions if their first execution didn't actually change anything, but rather returned early because it couldn't execute yet
So now I'm doing this:
            addNewEntityCommand = commandContext.createAddEntityCommand(tagChangeLogEntry.getEntity(), new AbstractCommand() {
                @Override
                protected void executeImpl() {
                    TagChangeCommand.this.executeImpl();
                }

                @Override
                protected void undoImpl() {
                    TagChangeCommand.this.undoImpl();
                }
            });
            addNewEntityCommand.execute();
Creating a new command that has as content what the old command did
i think I am doing things wrong.. subclassing a Tile for a special action when its a specific kind of tile:
public class TileCapital extends Tile {

	public TileCapital(Random random, MapPoint position) {
		super(random, Tile.TileType.CAPITAL, position);
		super.buildBuilding(Building.Type.TRADE_HUT);
	}

	private void increasePlayerInfluence() {

	}

	@Override
	public int playerSoldResource(Resource.Type resource) {
		this.increasePlayerInfluence();
		System.out.println("captialBought");
		return super.playerSoldResource(resource);
	}

	@Override
	public boolean playerBoughtResource(Resource.Type resource) {
@skiwi why not just put all of the actions in a queue and process them in order?
@bazola Because even in the case where they return early their status has been changed to executed and there's no way to undo that without messing around in the command pattern interface itself
@skiwi what would cause it to return early?
@bazola As an example I have a method that updates a tag on a player
Initially, it cannot find out to which entity the player belongs, so it cannot update it, puts itself in a backlog, and returns early
Then later once the mapping of entity to player has been discovered, it will pull the backlog and execute those commands
sounds confusing!
21:52
Not the easiest...
this HearthMonitor is a good exercise... but damn, it's hard
To be continued tomorrow...
One weird bug to go, and another weird bug to go
The former one only has an exception trace, only one observable weird thing; The latter one only has an observable thing, no exception trace
i wonder if this code makes any sense without context:
public void resourceSoldToPlayer(Resource.Type type) {
    int currentPrice = this.currentPrices.get(type);
    int increaseAmount = this.buyIncreaseAmounts.get(type);
    int maxPriceAmount = this.maxPriceAmounts.get(type);
    this.currentPrices.put(type, BZMaths.MIN(currentPrice + increaseAmount, maxPriceAmount));
}

public void resourcePurchasedFromPlayer(Resource.Type type) {
    int currentPrice = this.currentPrices.get(type);
    int decreaseAmount = this.sellDecreaseAmounts.get(type);
    this.currentPrices.put(type, BZMaths.MAX(currentPrice - decreaseAmount, 0));
@bazola Well, the method names and variable names make sense ;)
it is bad to have to access three or four different maps to get all the information needed but it will work until i figure out exactly what that information will be
Actually, I may see your issue there
You want to map the Resource.Type to an object containing current price, increase amount and max price amount
and on that object you want to have methods
TTGTB though
22:08
@skiwi night
22:22
I think I got the card set pretty well balanced now. @SimonAndréForsberg @bazola on your own convenience would you mind to just fire up 0.6 snapshot and copy the text from here into the phrancis-cards.cards file?
And see if you feel anything feels unbalanced
22:36
@Phrancis will do, most likely tomorrow
Super
I was too busy drinking beer with an old friend last night to tinker with ChucK some more, but I think I will tonight
22:51
its fun to play around with. I think it could work really well for making crazy sound effects
I'd like to see how easily that could be included in a Java project
(also, I don't know anything about whether Java is good with audio-related things)
bbl
23:07
@Phrancis included? you could make sounds and then export them as .wav and include the audio pretty easily
23:22
@Marc-Andre the AI isn't that smart. it mainly gives priority to certain actions.
@skiwi How would that even be possible? Why wouldn't one of your commands be able to change anything?
@bazola I would add a Building property on a Tile. So that the tile is the same, but it's building can be different, and the Building is the special one.
a TileCapital is a special kind of Tile though, not a building. It has a TradeBuilding that it uses in the background though
@skiwi I think you should parse more before even trying to execute it in those cases.
@bazola instead of BZMaths.MIN, why not Math.min ?
@skiwi that is absolutely an excellent suggestion for @bazola's code.
@SimonAndréForsberg i tried, and I could swear that it would not find the function or suggest the correct thing to import.. it was a fun exercise writing my own versions though:
public class BZMaths {

	public static int MIN(int a, int b) {
		if (a < b) {
			return a;
		} else {
			return b;
		}
	}

	public static int MAX(int a, int b) {
		if (a > b) {
			return a;
		} else {
			return b;
		}
	}

	public static int ABS(int a) {
		if (a < 0) {
			a = a * -1;
		}
		return a;
	}
}
@bazola for min: return a < b ? a : b; for max, the same but different. for abs: return a < 0 ? -a : a;
@SimonAndréForsberg yeah, instead of a HashMap for each type, I should have a HashMap with the Type and then the Object that contains that data. I am just doing it this way to figure out what actual data I am going to need before I do that
@SimonAndréForsberg i guess one day soon I need to graduate to ternary operators
23:32
@bazola but if you use an object then you can decide what actual data you need by editing the available properties of the object.
@bazola why is a TileCapital a special kind of Tile?
@SimonAndréForsberg that is true. cowboy programming for the win I guess
@bazola strange, I have never had problems with importing the Math class
@SimonAndréForsberg it has a different graphic on the map, for one, and it needs to handle special logic when the player buys and sells
@bazola cowboy programming? :)
Cowboy coding is software development where programmers have autonomy over the development process. This includes control of the project's schedule, languages, algorithms, tools, frameworks and coding style. A cowboy coder can be a lone developer or part of a group of developers working with minimal process or discipline. Usually it occurs when there is little participation by business users, or fanned by management that controls only non-development aspects of the project, such as the broad targets, timelines, scope, and visuals (the "what", but not the "how"). "Cowboy coding" commonly sees usage...
but what I really meant by that was, programming without thinking about the consequences first
@SimonAndréForsberg is there a way to do empty cells in a libGDX table? I finally figured out that table.row() starts a new row but I haven't figured out everything table related yet
23:41
@bazola describe the result that you want instead of the approach you expect is required to reach the result.
why would you want an empty cell?
well, i have one row of 3 cells, and then i want just one cell in the next row, positioned underneath the middle cell
thing.center() didn't work
use .colspan(3) for that cell
alright
and then .center(), I think
ah i see
pretty neat
23:43
you can have empty cells, but I don't think that's the correct approach usually. .colspan is better
they could have chosen a slightly better name for it, but it makes sense
this whole Tables thing is very complicated but also extremely powerful
the next thing I need to figure out is how to resize buttons, or actually resize cells of a table is more accurate
Just found out my wife's grandmother is in the ER on life support after she coded :(
(coded = cardiac arrest)
@Phrancis sorry to hear that
Thank you.
Probably not going to wake up from it, I gather. She's been in pretty bad shape lately
@bazola table.add(something).width(300).fillX() or how do you want them resized?
23:48
@SimonAndréForsberg yeah that looks like it will work
@Phrancis ouch. sorry to hear that :/ How old is she?
@Phrancis without that clarification, it would sound really strange...
@bazola you can also use .expand() on a cell, in either X, Y, or both directions. when used with .fill() it is awesome.
81 I think
so weird! Twice in a row when I first fired up this app on a device (once on the iPad and once on the iPod), the first time it fired up it did really strange behavior, like the opposite thing happened when i clicked a button, or like when I clicked the button nothing happened when it was supposed to
then the second time I run it, everything works as expected

« first day (208 days earlier)      last day (3652 days later) »