Giter Site home page Giter Site logo

evofighters's People

Contributors

deontologician avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

evofighters's Issues

Statistics tracking over time

Mostly, I don't actually care what the all-time total of statistics are. What I really want is to track statistics over time.

Stats to keep as a rate:

  • children born / second
  • kills / second
  • matings / second: should correlate with children born, but they can diverge a lot.
  • rounds / second

Stats to not keep anymore

  • mutations: this is a direct function of the mutation rate and the birth rate and isn't too interesting. Plus it requires we bubble up stats from deep in the mutation code.
  • feeders_eaten / second: this just isn't a very interesting stat

The idea is that we have the saver thread from #47 that we'll dump these stats to, and it can write them to disk in some format that allows us to save every data point (probably should be efficient, append-only and be cap-able in size.

Make the next_action part into a generator.

So at the beginning of an encounter, the generator is initialized with cycle(self.dna). In this way, we can avoid having to reinitialize the self.dna_cycler every fight (which I wanted to do), and also allow a more natural and encapsulated way to generate the next action of a guy. Also, we could pickle the creature directly, since it won't contain a cycle object!

This could also be used in conjunction with the fight context manager I want to make in issue #9

Make thoughts hashable so we can look them up if they already exist

If they're hashable, we can keep them in a hashmap to memoize them. Obviously only thoughts that are compiled/reduced should be hashed. This would serve two purposes:

  1. It would allow memory savings/ cache locality for common thoughts.
  2. It would allow easy lookup of what thoughts are currently succeeding

Does Rust have a weak hashmap? I could probably make one if not

Need to fold mating_phase and fighting_phase into a single "encounter"

Currently, mating is outside the purview of natural selection. It happens randomly and the only increased access to mating comes from being alive when the mating happens. This doesn't encourage competition, as all of the creatures tend to just stop fighting each other so they can soak up the sweet sweet rewards of living forever.

This enhancement would move mating from a separate phase into a single "encounter" phase, where creatures would encounter another creature and then decide whether to fight or mate (or both). I'd like to not program in rape explicitly, but at the same time, I don't think these creatures will be able to decide mutually to mate in their initial random states. Eventually they would be able to agree to a "mating ritual" etc, but initially we'll be counting on one of them having the idea to mate, and it being very unlikely the other one has the same idea at the same time.

Maybe a prisoner's dilemma tradeoff for mating?

Agree on mating: both share costs equally
One mates, the other does not mate: one who does not mate takes entire cost of mating
One mates, the other fights: Roll to see who wins?
Both don't mate: no mating happens

DNA representation to reduce malloc costs

I want to try doing arena allocations, or possibly sharing references to genes if possible (parent would pass an Rc pointer to children)

  • DNA = Vec(Gene)
  • `Gene = Rc<[i8]>

Mutations would need to be rethought since not all genes are copied, new genes can be created.

Command line improvements

Currently, the command line loop is a bit of a hack, it needs to be a list of commands and callbacks, rather than a massive elif tree.

-- Needs to support a help function
-- Needs to share common functionality in the same command (i.e. show this and show that should not have duplicated show code)
-- Needs to use readline so that we can press up and down and use regular line editing tricks

Make number of rounds before a time check adaptive

Right now in the main sim loop we don't check time every round because it's a system call and is pretty slow. So as a guess, we wait 1000 events or so before checking the time. This may or may not be right, but in any case it should be smarter.

  1. It should keep an average of how many rounds corresponded to how many seconds. This should be a trailing weighted average (everything past 5 rounds counts as 1, each of the past five rounds counts as 1).
  2. It should check how many rounds / second were actually happening, and then predict how many rounds it needs to wait until it checks the time again.

Make fullname show the genome in color

Basically, use shell output colors to show each element, rather than showing the number directly. This will give an easier visual inspection of the genome.

Precompilation of creature dna to thoughts

This involves both simplifying, and cycle detection, so we can pre-evaluate thoughts, and not have to parse them from scratch each time.

  1. Need to simplify based on the creature, and which values are static.
  2. Need to cycle detect and pre-build the thought loop

Convert save file format to sqlite.

This should make it

  • Easier to query different properties of creatures for statistics
  • Possibly faster to load data
  • Lead to a better serialization format than pickling
  • Create a natural way to create and manipulate census data

Possible downsides:

  • Possibly slower to get data
  • A large rewrite which might result in a lot of breakages

Need a way to "promote" items

Right now everyone uses the worst item (value 1). We need a way for a creature to combine his own items into a more energy dense item form.

Ideas:

  1. Do it automatically for him
  2. Have a new command that does it
  3. Have some combination of actions do it

Make it easy to install and run the main program

Currently, the way I've been running the program has been to activate the virtualenv and then go into the EvoFighters directory and do python Arena.py. This is less than optimal, as Arena.py doesn't stand out in any way and isn't very user friendly.

Best thing to do is modify setup.py to create an EvoFighters executable/script

Make savefile configurable and use the ~/.config/EvoFighters directory

Currently, the savefile is hardcoded, there are several improvements that need to be made:

  1. Set the default save directory to ~/.config/EvoFighters
  2. Make the savefile name configurable
  3. Allow the user to pick from among different save files
  4. Allow the user to duplicate save files
  5. Allow the user to merge save files safely
  6. Allow the user to split save files safely
  7. Use sqlite and save statistics per generation?

DRY up parsing code

Currently, the parsing code is really really repetitive and has lots of copy + pasting. This needs to be rectified.

Add more functions to reduce duplicated code in the parser

Add feeder creatures

In order to get feeding into the adaptation, add a creature who is just a stand in to provide food with the following properties:

  1. Has an item in its inventory
  2. Always Signals "green"
  3. Always "waits" after using maximum thinking time (simulated of course)
  4. Mating with the creature produces no offspring
  5. Has 1 energy
  6. Should "die" if their inventory is empty or they have no energy

Killing the creature allows the creature to get the item, or the creature can just "take" the item during the encounter.

This should be an elegant solution to allowing the creatures to have heritable control over feeding behavior, but not distract them from their main goal of fighting! (Alternatives could have been some harvesting phase or something else)

Running evofighters on a gpu

Looks like this isn't super feasible right now, but to track what kinds of options are out there:

  1. Rewrite main encounter code in cuda/opencl (nope, don't feel like it)
  2. Use something like rlsl or inspirv-rust to compile the main encounter code to a kernel to run on a gpu (SPIR-V is an intermediate language compiled by a gpu driver, and is fairly well supported vs older methods of telling the gpu what to do

I think if these projects get off the ground, it could be very feasible to move the main simulation code into a gpu kernel. The main issue at the moment is:

  • these project's maturity is very low
  • they rely on unstable features of the rust compiler
  • they go straight from MIR -> SPIR-V, and so don't gain the optimization benefits available to LLVM (which is currently where most rust optimization comes from. I believe there are very few optis in Rust -> MIR) so the kernel could be significantly slower
  • SPIR-V doesn't represent everything from rust super well, it might require a huge rewrite

Emulate genotype/phenotype for diversity

Essentially, a gene would have two versions, one from each parent, and when it simulates a thought, it would run "next valid" on both of them, returning the first valid value.

If two valid responses, we could come up with some non-commutative function to calculate which value wins

If they are the same response, obviously that would be returned.

Allow variable feeder populations

Might want to be able to have the master thread control the feeder supply (not simply being max - real creatures). This would correspond to like "famine times" etc, in which things "get malthusian bruh"

Create tools to examine the save file

Since live viewing of the simulation isn't currently possible in the Rust version (owing to poor signal handling libraries). We just save the state periodically.

What we need are tools to rip through the json file of the state and get stats the way the original python version did. It can even be written in python since it's just doing analytics and not the simulation

Add a README

Describing how to run the program, and the commands that are available, as well as a rough overview of the application

Multithreading

Basic idea:

  • 1 master thread that knits together the results from the workers and hands out jobs
  • 1 worker thread per physical core, these do the simulation
  • 1 saver thread that handles writing to disk both stats (which are frequent) and checkpoints (which are rare)

In the future, I may add a thread for a webserver

Crashing bug

Creating initial population
Created 120001 creatures
Creatures: 118479thread 'main' panicked at 'index out of bounds: the len is 0 but the index is 0', /checkout/src/liballoc/vec.rs:1561:14S: 5.0       
stack backtrace:
   0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace
             at libstd/sys/unix/backtrace/tracing/gcc_s.rs:49
   1: std::sys_common::backtrace::print
             at libstd/sys_common/backtrace.rs:68
             at libstd/sys_common/backtrace.rs:57
   2: std::panicking::default_hook::{{closure}}
             at libstd/panicking.rs:380
   3: std::panicking::rust_panic_with_hook
             at libstd/panicking.rs:396
             at libstd/panicking.rs:576
   4: std::panicking::begin_panic
             at libstd/panicking.rs:537
   5: std::panicking::begin_panic_fmt
             at libstd/panicking.rs:521
   6: core::panicking::panic_fmt
             at libstd/panicking.rs:497
             at libcore/panicking.rs:71
   7: core::panicking::panic_bounds_check
             at libcore/panicking.rs:58
   8: evofighters::dna::DNA::combine
   9: evofighters::creatures::try_to_mate
  10: evofighters::arena::do_round
  11: evofighters::arena::simulate
  12: evofighters::run_simulation
  13: evofighters::main
  14: std::rt::lang_start::{{closure}}
  15: std::panicking::try::do_call
             at libstd/rt.rs:59
             at libstd/panicking.rs:479
  16: std::rt::lang_start_internal
             at libpanic_unwind/lib.rs:102
             at libstd/panicking.rs:458
             at libstd/panic.rs:358
             at libstd/rt.rs:58
  17: main
  18: __libc_start_main
  19: _start
Creatures: 30663, Feeders: 89337, F/C: 2.914, Mutations: 3039, Events: 3508611, Born: 30679, Eaten: 218597, kills: 62881, eps: 473102, err: -91.5%, FPS: 2.6

Change mating costs

Currently, mating has a fixed cost in terms of items and/or life. I'd like it to be a bit more sophisticated along these lines:

mating_cost = 10
while mating_cost > 0 and self.alive:
    if self.inv:
        item = self.inv.pop()
        mating_cost -= item + 1
    else:
        self.energy -= mating_cost

And if you kill yourself, you don't have a child.

Different damage types should do different things

Originally, the plan was for damage types to have a rock/paper/scissors scheme in terms of attack versus defense. Once the attack/defend/mate matrix was put in place, however, this plan fell by the wayside. That needs to be implemented again, taking into account attack vs. defense only.

|-------------+------+------+-------------|
|             | fire |  ice | electricity |
|-------------+------+------+-------------|
| fire        | 0.33 | 0.66 |         1.0 |
| ice         |  1.0 | 0.33 |        0.66 |
| electricity | 0.66 |  1.0 |        0.33 |
|-------------+------+------+-------------|

Add command line options, and a banner when the program starts

 _______          _______ _       _                         
(_______)        (_______|_)     | |    _                   
 _____ _   _ ___  _____   _  ____| | _ | |_  ____  ____ ___ 
|  ___) | | / _ \|  ___) | |/ _  | || \|  _)/ _  )/ ___)___)
| |____\ V / |_| | |     | ( ( | | | | | |_( (/ /| |  |___ |
|_______)_/ \___/|_|     |_|\_|| |_| |_|\___)____)_|  (___/ 
                           (_____|                          

Add more instruction types for a fight

Once issue #2 is completed, add a few more actions and triggers like:

random - generates a random number between -1 and 9
flee - escape the fight (whether fleeing works is a random roll weighted by respective energy levels)
mate - attempt to mate with the opponent

Create "epochs" for diversity

Once the simulation is multithreaded, we can decide to mix populations every so often with a concept of "epochs". Keeping them isolated and co-evolving, then mixing some together

"simulate" is totally broken!

No save file found, creating a new generation!
command> simulate
Traceback (most recent call last):
  File "Arena.py", line 330, in <module>
    sd.progress)
TypeError: generationer() takes at least 4 arguments (3 given)

Mating has to cost something

Currently, the population goes off the rails once creatures realize they need to make love and not war. Mating needs to cost something so that there is a tradeoff and not an "always best" strategy of not fighting.

Thinking mating could cost one food or 5 life if there is no food.

Make an "encounter" context manager

This will be useful for almost nothing, but might make the code cleaner. The object of the with statement should be a newly initialized next_action generator from issue #8

Add an "extension" action and condition

I really don't want to make higher numbers than 9, so there'll need to be an 'extension' digit that means the next number signifies the actual code is in a second lookup table.

This will allow more conditions like:

  • Enemy is age X
  • Enemy has won X encounters
  • Enemy has survived X encounters

Make gene splicer better at making small genes

Right now it is hell bent on making absolutely massive genes.

It should have a heuristic like "after 5 bases, there's a 1 in 10 chance it'll split the gene after each base. If it sees a -1, always split"

This should cut down on the "whole genome is one gene" problem that currently plagues the system.

More reductions for simplify

  • If the affirmed/denied branches are equal, then Always(action)
  • simplify_action should convert Subcondition(Always(X)) ->X
  • Some simple comparisons to static properties of a creature could be analyzed with data from the creature:
    • generation is static per creature
  • If the last action is inside a cycle and is known statically, then if the next action does an actioncompare, we know it statically
  • If a creature checks what his signal is, and he has no actions that change his signal, we know the outcome statically.

Add ability to compare self and target attributes

Currently, attributes are compared against absolute numbers in the dna, but comparisons could be changed to allow specification of attributes to compare against instead of a number. This would probably be most easily changed in the Compare non-terminal.

Really rich comparisons could work by adding a new non-terminal to comparisons that allows an attribute to be specified
Probably, instead of exhaustively listing attributes, we could do something along the lines of:

COMPARE :: inrange VAL VAL | lessthan VAL | greaterthan VAL | equalto VAL | notequalto VAL
VAL :: int (INT) | me ATTR | you ATTR
ATTR :: generation | kills | survived | matings | energy | signal

Allow all settings to be specified as options on the command line

Settings need to stop being globally static, since we have to be able to save and load them from a file (currently they're being saved but being ignored when they're loaded again).

I think it's fine not to have a config file for this, but we should at least take command line args.

Probably should use lazy_static or something? Maybe not.

Get rid of Phases!

Phases just artificially restrict how the selection process can occur. If feeding is integrated into encounters (#14), and fighting and mating are integrated (#5), then there is no real reason to maintain the phase distinction. Because of this, several things need to change:

Won: Encounters need not be "won" in the traditional sense if one is mating. Better to keep track of Kills directly.

Age: No longer means anything without distinct phases. We could add an "every X fights, increment all of the ages", but that is pretty superfluous. Keeping track of kills and encounters survived should serve any purpose age served.

Generation: This should now be a property of each individual creature, which is equivalent to the maximum generation of the parents plus one. Arguably, this change should have been made before, since all creatures in "a generation" are not necessarily the same number of descendants from the the first generation.

Mating is too effective a weapon

Currently, mating is the most effective way to kill another creature. There needs to be a cost to mating that doesn't involve killing the opponent so they are forced to actually use their attacks.

I am thinking if one does not have enough food, mating doesn't occur, but it doesn't damage anyone either

How many fights to have needs to be recalculated more often

Currently, how many fights to have depends on the population size before the fights start occurring. I think the estimated number of fights needs to go down as the population goes down. So conceptually, we would have a percentage variable that always tells you how far along the fights are. Then every X deaths or so, the number of fights total is recalculated, and then the percentage is taken out of that. In this way, the percentage till done is always known, but the actual number of fights to have goes down and doesn't risk the current "catastrophic loss" situation, where fighters are very effective an quickly whittle down a huge population to a small one, but the total fights number keeps pitting them against each other.

This would also allow removal of the "10 population or less" failsafe, which is actually a terrible failsafe since the population is already dangerously low on genetic diversity at that point.

Add gene tracking statistics.

As part of timeline statistics:

  • record the number of unique genes in the gene pool (ordered by similarity if feasible)
  • the number of instances of the gene in the pool

This should give a good view over time of how genes change, when genes become more successful, and when they die out.

Merge parsing and evaluation into one.

Currently, the parser spends a lot of time creating massive trees of contingencies that never get evaluated because an if branch goes another way higher up in the tree. It might make sense (and allow more flexible bots), for evaluation to occur at parse time, since that information is known. In this way, we could prune parse trees that aren't followed early on.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.