Fork me on GitHub
#clojure
<
2016-08-14
>
danielcompton02:08:34

@amacdougall: in our projects we have src/cljc src/cljs src/clj

danielcompton02:08:51

this makes it easy to know which files are running in which environment

bostonaholic02:08:18

^^ that’s the convention I follow

seylerius07:08:57

My for loop in sync-files isn't firing: http://sprunge.us/cXQe

seylerius07:08:12

I don't quite get why.

hans07:08:59

@seylerius: just a shot in the dark, but maybe you rather want doseq?

azel07:08:08

@seylerius: yes, you want doseq. for yields a lazy sequence (see docs), thus side effects will only be realized when consumed. And your code example does not consume the resulting list.

pesterhazy10:08:54

@yonatanel: cool. Something similar to django's admin for datomic would be great

pesterhazy10:08:43

Pretty sure that datomic's superpowers help make a great, general crud tool

renlore13:08:33

is seesaw the primary library for GUI?

bur13:08:44

Is someone using Lighttable?

bur13:08:53

I don't have autocomplete in javascript

seylerius18:08:12

@hans, @azel: Yep. doseq did the trick. Thanks.

seylerius18:08:45

Now I'm having trouble with command line options. Here's my repo: https://github.com/seylerius/org-collect

amacdougall23:08:05

For personal edification, I'm playing around with room-based maps, similar to those used in interactive fiction or old-school MUDs. Eventually I want to write a program which generates plausible random maps, but I'm starting with the much simpler task of implementing such a system. Really just asking for a sanity check at this point on various aspects of the data. 1. Each collection of rooms at a certain map scale (overworld, city, dungeon, etc) is called a "zone". I think it's appropriate for the zone to contain a list of all rooms, where a room knows what characters and items and stuff are in it... like, {:rooms [{:id :name-of-room, :name "Name of Room", :characters [:char-id-a, :char-id-b]}, ...]}. The character ids are keys into a character list stored elsewhere. So far, so good, but looking up a room by id, or finding what room a character is in, becomes O(n) at best. So I'm thinking the zone would include lookup tables, which we'd have to update whenever something changes: {:rooms [...], :rooms-by-id {:room-id room, ...}, :rooms-by-character-id {:char-id-a :room-id, ...}}. But something tells me this is too baroque. 2. To move a character around, I expect to pass in the entire zone, a target character, and a direction; and get back a zone where the character has moved in the desired direction. (zone/move zone character ::zone/w), for instance. This should be fine, since it's how Clojure is meant to work, and Specter will make it easier to get deep in the data structure and tinker with it. But consider that I'm planning to store the entire game state in a single atom and transact everything; basically, am I doing it right? 3. Finally, as I began writing tests for some of this stuff, I realized that it's irritating to account for nil values. I supposed I should just use generative testing and treat any unexpected nil input as a hard error.

akiva23:08:22

I’d write it so that a room doesn’t know what character is in it; rather a character knows what room its in.

sgerguri23:08:34

The general approach of having zones that contain rooms which contain characters is sound.

sgerguri23:08:39

Now onto specifics:

lvh23:08:09

You might want to look at datascript or something if you really end up needing to “look at the same data from different angles” — sounds unlikely, though, and you probably just want a character to have a reference to a room 🙂

lvh23:08:32

datalog makes the referency bit a little easier though

sgerguri23:08:01

1. The rooms do not have to be a list - unless you expect to do frequent processing of all rooms in the zone. Your map can look as follows:

{:room1 :characters [:char-id-a :char-id-b]
 :room2 :characters [:char-id-c :char-id-d]}
I'm basically turning the list of rooms into an index of them, by their idea, into the characters they contain.

amacdougall23:08:55

Well, if the character knows what room it is in, as in {:location <room id>}, we need to do a lookup any time we want more information about the room, right?

sgerguri23:08:33

3. I'd be tempted to say that you should make it as nil-compliant as possible. Look at the standard library, nil serves as the unit value for many (all?) of the functions, but it's hard to say without having the overall design goals in my head.

amacdougall23:08:34

I'm assuming everything wants to be linked by ids, since multiple collections cannot have references to the same value in Clojure.

amacdougall23:08:26

Oh duh, of course we have {:rooms {:room-id <data>, :room-id-b <data>, ...}.

amacdougall23:08:16

I played with this, but I realized that the room id should also be part of the room data itself, and it seemed awkward to do this:

{:rooms
 {:cave-entrance
  {:id :cave-entrance, ...}}}

amacdougall23:08:26

Redundant, at least. Then again, my ultimate goal is to generate maps randomly, so who cares if there's some redundant data? The computer doesn't get bored.

amacdougall23:08:35

Oh, and my reasoning for giving each room a list of character ids is that an extremely common use case will be to display a room description including a list of characters. But of course, it will be just as common to say "it's this character's turn to move, what's their situation?"

amacdougall23:08:43

So neither approach is completely ideal.

sgerguri23:08:47

You can also introduce a separate index for the mapping between rooms and characters, and let that be completely independent of your set of rooms and characters, rather than keep everything nested in one data structure - since I presume this is static data?

amacdougall23:08:25

As for handling nil, a command like (can-move? zone character direction) can certainly be false if any of the arguments are nil, but since a nil argument in this case indicates a programming error, I think immediate failure is appropriate. I'll take it case by case and try to handle nils anywhere they might reasonably be valid.

amacdougall23:08:01

Yeah, I expect characters to move around, but I don't expect the map itself to change. Maintaining a room->characters map and a character->room map might be reasonable. On the other hand, inspired by re-frame, I want to keep the game state in a single atom. I'm sold on the virtues of that approach. So ultimately everything is going to be a property of a huge map.

sgerguri23:08:29

You still can with the above - just have a map with two indices inside.

amacdougall23:08:58

Right. The subtree for a single zone would be something like {:rooms <map of room ids to room records>, :character-locations <map of character ids to room ids>, :room-inhabitants <map of room ids to character id vectors>}, I think.

sgerguri23:08:05

One thing to consider is whether you intend the characters themselves to change or not (i.e., are they maps that will change over time?). That might play into how you end up designing things.

amacdougall23:08:10

Each character record (probably not literally defrecord records, but maps with clojure-speced contents) will definitely have values that change over time. This will probably never see the light of day, but I ultimately want to make a single-player RPG, so health etc will change.

amacdougall23:08:25

As a result, I definitely want to store each character's data in one place and refer to it by id, instead of copying it around the game state.

sgerguri23:08:38

I'd be tempted to separate static data from variable ones - stuff like room info could be static and not be part of the "mutable" state.