Python: steps for distributing a work?

You must include the MIT license and the copyright notice:

Copyright (c) 2014 Phillip Johnson
1 Like

So, it’s copyright by Philip Johnson.
Then I doubled the size of the program. How will that change the copyright notice? Do I put in 2 names there?
Also, let’s say that there’s a long subroutine that gets modified in lots of places. It’s easy to see with diff, who does what, but there’s multiple authors denoting multiple fixes. How will the attribution done? Sorry if these are basic questions, but I generally stayed away from mixing other people’s code, and so have no experience regarding proper usage of multiple author attribution.

The usual plan is to add a line saying “Portions copyright 2021 by <your name>.” You don’t have to provide a detailed accounting of which parts were written by who.

1 Like

With open source software, including the original copyright not only gives attribution to the original author, it preserves and ensures the intent that the code remains open source and cannot be converted to commercial use only.

OK. Thanks for the info.

The best way to do that, I think, is make a Python library for making IF. An IF game engine written in Python. A single IF game written in Python probably isn’t going to change anything, but if you generalize the framework for your game into something people can easily reuse, that might be interesting.

I thought every prospective IF player made their own IF as well?

Just kidding. Or am I?

The problem with technical skills is that they are varied. Just because people are using Inform7, doesn’t mean they use Javascript, Python, or even Inform6. And vice-versa.

Another factor to consider is framework. Just because I use Perl, doesn’t mean I’m comfortable reading/using everybody’s Perl code. Ditto with C. Simply because the program uses different framework than what I’m used to.

This is why Programmer’s Journal/Design Document is such an important part of code sharing. I don’t even bother with the source code anymore. Show me your code, and I’ll continue to be mystified. Show me your documentation, and I don’t need your code. It’ll be obvious. Paraphrasing a famous someone. :slight_smile:

Funny you should say that :wink:
This is my long term goal. Currently I’m working on three separate Python packages.

It’s all starting to fit into place. But it’ll be a few months before they’re good enough for wider use.

5 Likes

Will you be able to release a compiled version on the game or will it still be a runtime requiring a python installation?

I’m hoping to support two models; hosting on the web and playing locally. I’m not aware of anything that would stop you from creating an OS-specific executable (using cx_freeze for example) in the second case.

2 Likes

Ever consider Julia?

I wasn’t aware of Julia. I expect it has a smaller user base than Python?

1 Like

Julia is a relatively new language similar to Python. The user base is much smaller than Python. I actually considered it for developing experimental IF and looked into its string handling capability. I wasn’t satisfied a couple of years ago. It is evolving and may be worth consideration for a new project that you are writing most of the modules and libraries from scratch.

If we’re suggesting languages, the next one that I intend to play around with is Dart used in combination with Flutter. I don’t think Dart took off like people were hoping but I still think it’s a pretty cool language. It’s developed by Google and the syntax kind of falls somewhere between Javascript, C++, and C#. Dart is the language and Flutter is the UI SDK, kind of like Java and JavaFX, or C# and Unity.

The reason I’m suggesting it is that Dart and Flutter both compile to windows, linux, mac, android, ios, and web (dart transpiles to JS).

Does Dart have any relation to Go?

I don’t believe so. Dart was developed after Go by a different group and was used for internal use before being released publicly. Dart was focused on cross platform releases for desktop/mobile/web, whereas Go was focused on making server-side or command line apps. Go doesn’t even have a windowing library available for it yet.

The languages are also very different in syntax. Go kind of reminds me of a combination of C and Pascal.

Dart Example
import 'dart:convert';
import 'dart:io';

import 'package:args/args.dart';

const lineNumber = 'line-number';

void main(List<String> arguments) {
  exitCode = 0; // presume success
  final parser = ArgParser()..addFlag(lineNumber, negatable: false, abbr: 'n');

  ArgResults argResults = parser.parse(arguments);
  final paths = argResults.rest;

  dcat(paths, showLineNumbers: argResults[lineNumber] as bool);
}

Future<void> dcat(List<String> paths, {bool showLineNumbers = false}) async {
  if (paths.isEmpty) {
    // No files provided as arguments. Read from stdin and print each line.
    await stdin.pipe(stdout);
  } else {
    for (final path in paths) {
      var lineNumber = 1;
      final lines = utf8.decoder
          .bind(File(path).openRead())
          .transform(const LineSplitter());
      try {
        await for (final line in lines) {
          if (showLineNumbers) {
            stdout.write('${lineNumber++} ');
          }
          stdout.writeln(line);
        }
      } catch (_) {
        await _handleError(path);
      }
    }
  }
}

Future<void> _handleError(String path) async {
  if (await FileSystemEntity.isDirectory(path)) {
    stderr.writeln('error: $path is a directory');
  } else {
    exitCode = 2;
  }
}
Go Example
package main

import (
	"fmt"
	"math/rand"
)

const (
	win            = 100 // The winning score in a game of Pig
	gamesPerSeries = 10  // The number of games per series to simulate
)

type score struct {
	player, opponent, thisTurn int
}

type action func(current score) (result score, turnIsOver bool)

func roll(s score) (score, bool) {
	outcome := rand.Intn(6) + 1 // A random int in [1, 6]
	if outcome == 1 {
		return score{s.opponent, s.player, 0}, true
	}
	return score{s.player, s.opponent, outcome + s.thisTurn}, false
}

func stay(s score) (score, bool) {
	return score{s.opponent, s.player + s.thisTurn, 0}, true
}

type strategy func(score) action

func stayAtK(k int) strategy {
	return func(s score) action {
		if s.thisTurn >= k {
			return stay
		}
		return roll
	}
}

func play(strategy0, strategy1 strategy) int {
	strategies := []strategy{strategy0, strategy1}
	var s score
	var turnIsOver bool
	currentPlayer := rand.Intn(2) // Randomly decide who plays first
	for s.player+s.thisTurn < win {
		action := strategies[currentPlayer](s)
		s, turnIsOver = action(s)
		if turnIsOver {
			currentPlayer = (currentPlayer + 1) % 2
		}
	}
	return currentPlayer
}

func roundRobin(strategies []strategy) ([]int, int) {
	wins := make([]int, len(strategies))
	for i := 0; i < len(strategies); i++ {
		for j := i + 1; j < len(strategies); j++ {
			for k := 0; k < gamesPerSeries; k++ {
				winner := play(strategies[i], strategies[j])
				if winner == 0 {
					wins[i]++
				} else {
					wins[j]++
				}
			}
		}
	}
	gamesPerStrategy := gamesPerSeries * (len(strategies) - 1) // no self play
	return wins, gamesPerStrategy
}

func ratioString(vals ...int) string {
	total := 0
	for _, val := range vals {
		total += val
	}
	s := ""
	for _, val := range vals {
		if s != "" {
			s += ", "
		}
		pct := 100 * float64(val) / float64(total)
		s += fmt.Sprintf("%d/%d (%0.1f%%)", val, total, pct)
	}
	return s
}

func main() {
	strategies := make([]strategy, win)
	for k := range strategies {
		strategies[k] = stayAtK(k + 1)
	}
	wins, games := roundRobin(strategies)

	for k := range strategies {
		fmt.Printf("Wins, losses staying at k =% 4d: %s\n",
			k+1, ratioString(wins[k], games-wins[k]))
	}
}
1 Like